@metamask/social-controllers 3.4.0 → 3.5.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.5.0]
11
+
12
+ ### Added
13
+
14
+ - Add `SocialRealtimeService` for subscribing to Social realtime feed events through the shared backend WebSocket connection ([#10561](https://github.com/MetaMask/core/pull/10561))
15
+
16
+ ### Changed
17
+
18
+ - Bump `@metamask/base-data-service` from `^2.0.0` to `^2.1.0` ([#10502](https://github.com/MetaMask/core/pull/10502))
19
+ - Bump `@metamask/core-backend` from `^11.0.0` to `^12.0.0` ([#10648](https://github.com/MetaMask/core/pull/10648))
20
+
10
21
  ## [3.4.0]
11
22
 
12
23
  ### Added
@@ -225,7 +236,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
225
236
  - `unfollowTrader` — unfollows traders and removes addresses from state
226
237
  - `updateFollowing` — fetches following list and replaces addresses in state
227
238
 
228
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/social-controllers@3.4.0...HEAD
239
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/social-controllers@3.5.0...HEAD
240
+ [3.5.0]: https://github.com/MetaMask/core/compare/@metamask/social-controllers@3.4.0...@metamask/social-controllers@3.5.0
229
241
  [3.4.0]: https://github.com/MetaMask/core/compare/@metamask/social-controllers@3.3.0...@metamask/social-controllers@3.4.0
230
242
  [3.3.0]: https://github.com/MetaMask/core/compare/@metamask/social-controllers@3.2.0...@metamask/social-controllers@3.3.0
231
243
  [3.2.0]: https://github.com/MetaMask/core/compare/@metamask/social-controllers@3.1.0...@metamask/social-controllers@3.2.0
@@ -0,0 +1,34 @@
1
+ import type { BackendWebSocketServiceMessenger } from '@metamask/core-backend';
2
+ import type { FeedItem } from './social-types.js';
3
+ export declare const SOCIAL_FEED_CHANNEL: 'social.v1.feed.all';
4
+ export declare const SOCIAL_FEED_CHANNEL_TYPE: 'social.v1';
5
+ export type SocialFeedEvent = {
6
+ version: 1;
7
+ kind: 'feed-item';
8
+ eventId: string;
9
+ feedItemId: string;
10
+ revision: number;
11
+ occurredAt: string;
12
+ data: FeedItem;
13
+ };
14
+ export type SocialFeedEventListener = (event: SocialFeedEvent) => void;
15
+ export type SocialFeedReconnectListener = () => void;
16
+ export type SocialRealtimeServiceOptions = {
17
+ messenger: BackendWebSocketServiceMessenger;
18
+ isEnabled?: () => boolean;
19
+ };
20
+ /**
21
+ * Social realtime subscription service built on the shared backend WebSocket.
22
+ *
23
+ * The POC subscribes to the global feed channel. Additional Social channels
24
+ * can be added here without creating another WebSocket connection.
25
+ */
26
+ export declare class SocialRealtimeService {
27
+ #private;
28
+ readonly name: 'SocialRealtimeService';
29
+ constructor({ messenger, isEnabled, }: SocialRealtimeServiceOptions);
30
+ addListener(listener: SocialFeedEventListener): () => void;
31
+ addReconnectListener(listener: SocialFeedReconnectListener): () => void;
32
+ setActive(active: boolean): Promise<void>;
33
+ }
34
+ //# sourceMappingURL=SocialRealtimeService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SocialRealtimeService.d.ts","sourceRoot":"","sources":["../src/SocialRealtimeService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gCAAgC,EAGjC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,eAAO,MAAM,mBAAmB,EAAG,oBAA6B,CAAC;AACjE,eAAO,MAAM,wBAAwB,EAAG,WAAoB,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,CAAC,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AACvE,MAAM,MAAM,2BAA2B,GAAG,MAAM,IAAI,CAAC;AAErD,MAAM,MAAM,4BAA4B,GAAG;IACzC,SAAS,EAAE,gCAAgC,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;CAC3B,CAAC;AAuBF;;;;;GAKG;AACH,qBAAa,qBAAqB;;IAChC,QAAQ,CAAC,IAAI,EAAG,uBAAuB,CAAU;IAkBjD,YAAY,EACV,SAAS,EACT,SAA+B,GAChC,EAAE,4BAA4B,EAyB9B;IAED,WAAW,CAAC,QAAQ,EAAE,uBAAuB,GAAG,MAAM,IAAI,CAGzD;IAED,oBAAoB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM,IAAI,CAGtE;IAEK,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9C;CAyEF"}
@@ -0,0 +1,126 @@
1
+ import { WebSocketState } from '@metamask/core-backend';
2
+ export const SOCIAL_FEED_CHANNEL = 'social.v1.feed.all';
3
+ export const SOCIAL_FEED_CHANNEL_TYPE = 'social.v1';
4
+ const isRecord = (value) => typeof value === 'object' && value !== null;
5
+ const parseSocialFeedEvent = (data) => {
6
+ if (data.version !== 1 ||
7
+ data.kind !== 'feed-item' ||
8
+ typeof data.eventId !== 'string' ||
9
+ typeof data.feedItemId !== 'string' ||
10
+ typeof data.revision !== 'number' ||
11
+ typeof data.occurredAt !== 'string' ||
12
+ !isRecord(data.data)) {
13
+ return undefined;
14
+ }
15
+ return data;
16
+ };
17
+ /**
18
+ * Social realtime subscription service built on the shared backend WebSocket.
19
+ *
20
+ * The POC subscribes to the global feed channel. Additional Social channels
21
+ * can be added here without creating another WebSocket connection.
22
+ */
23
+ export class SocialRealtimeService {
24
+ name = 'SocialRealtimeService';
25
+ #messenger;
26
+ #listeners = new Set();
27
+ #reconnectListeners = new Set();
28
+ #isEnabled;
29
+ #active = false;
30
+ #subscription;
31
+ #subscriptionPromise;
32
+ #wasDisconnected = false;
33
+ constructor({ messenger, isEnabled = () => true, }) {
34
+ this.#messenger = messenger;
35
+ this.#isEnabled = isEnabled;
36
+ this.#messenger.subscribe('BackendWebSocketService:connectionStateChanged', ({ state }) => {
37
+ if (state === WebSocketState.DISCONNECTED) {
38
+ this.#subscription = undefined;
39
+ this.#wasDisconnected = true;
40
+ }
41
+ if (state === WebSocketState.CONNECTED && this.#active) {
42
+ const isReconnect = this.#wasDisconnected;
43
+ this.#wasDisconnected = false;
44
+ // Subscription setup handles its own errors and must not block reconnect handling.
45
+ // eslint-disable-next-line no-void
46
+ void this.#subscribeToFeed();
47
+ if (isReconnect) {
48
+ this.#reconnectListeners.forEach((listener) => listener());
49
+ }
50
+ }
51
+ });
52
+ }
53
+ addListener(listener) {
54
+ this.#listeners.add(listener);
55
+ return () => this.#listeners.delete(listener);
56
+ }
57
+ addReconnectListener(listener) {
58
+ this.#reconnectListeners.add(listener);
59
+ return () => this.#reconnectListeners.delete(listener);
60
+ }
61
+ async setActive(active) {
62
+ this.#active = active && this.#isEnabled();
63
+ if (!this.#active) {
64
+ await this.#unsubscribeFromFeed();
65
+ return;
66
+ }
67
+ await this.#subscribeToFeed();
68
+ }
69
+ async #subscribeToFeed() {
70
+ if (!this.#active || this.#subscription) {
71
+ return;
72
+ }
73
+ while (this.#subscriptionPromise) {
74
+ await this.#subscriptionPromise;
75
+ if (!this.#active || this.#subscription) {
76
+ return;
77
+ }
78
+ }
79
+ const subscriptionPromise = Promise.resolve().then(async () => {
80
+ try {
81
+ await this.#messenger.call('BackendWebSocketService:connect');
82
+ // Each service needs its own callback and subscription lifecycle.
83
+ const subscription = await this.#messenger.call('BackendWebSocketService:subscribe', {
84
+ channels: [SOCIAL_FEED_CHANNEL],
85
+ channelType: SOCIAL_FEED_CHANNEL_TYPE,
86
+ callback: (notification) => {
87
+ this.#handleNotification(notification);
88
+ },
89
+ });
90
+ if (!this.#active) {
91
+ await subscription.unsubscribe();
92
+ return;
93
+ }
94
+ this.#subscription = subscription;
95
+ }
96
+ catch {
97
+ this.#subscription = undefined;
98
+ }
99
+ });
100
+ this.#subscriptionPromise = subscriptionPromise;
101
+ try {
102
+ await subscriptionPromise;
103
+ }
104
+ finally {
105
+ this.#subscriptionPromise = undefined;
106
+ }
107
+ }
108
+ async #unsubscribeFromFeed() {
109
+ const subscription = this.#subscription;
110
+ this.#subscription = undefined;
111
+ if (subscription) {
112
+ await subscription.unsubscribe();
113
+ }
114
+ }
115
+ #handleNotification(notification) {
116
+ if (notification.channel !== SOCIAL_FEED_CHANNEL) {
117
+ return;
118
+ }
119
+ const event = parseSocialFeedEvent(notification.data);
120
+ if (!event) {
121
+ return;
122
+ }
123
+ this.#listeners.forEach((listener) => listener(event));
124
+ }
125
+ }
126
+ //# sourceMappingURL=SocialRealtimeService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SocialRealtimeService.js","sourceRoot":"","sources":["../src/SocialRealtimeService.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebSocketState } from '@metamask/core-backend';\nimport type {\n BackendWebSocketServiceMessenger,\n ServerNotificationMessage,\n WebSocketSubscription,\n} from '@metamask/core-backend';\n\nimport type { FeedItem } from './social-types.js';\n\nexport const SOCIAL_FEED_CHANNEL = 'social.v1.feed.all' as const;\nexport const SOCIAL_FEED_CHANNEL_TYPE = 'social.v1' as const;\n\nexport type SocialFeedEvent = {\n version: 1;\n kind: 'feed-item';\n eventId: string;\n feedItemId: string;\n revision: number;\n occurredAt: string;\n data: FeedItem;\n};\n\nexport type SocialFeedEventListener = (event: SocialFeedEvent) => void;\nexport type SocialFeedReconnectListener = () => void;\n\nexport type SocialRealtimeServiceOptions = {\n messenger: BackendWebSocketServiceMessenger;\n isEnabled?: () => boolean;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null;\n\nconst parseSocialFeedEvent = (\n data: Record<string, unknown>,\n): SocialFeedEvent | undefined => {\n if (\n data.version !== 1 ||\n data.kind !== 'feed-item' ||\n typeof data.eventId !== 'string' ||\n typeof data.feedItemId !== 'string' ||\n typeof data.revision !== 'number' ||\n typeof data.occurredAt !== 'string' ||\n !isRecord(data.data)\n ) {\n return undefined;\n }\n\n return data as unknown as SocialFeedEvent;\n};\n\n/**\n * Social realtime subscription service built on the shared backend WebSocket.\n *\n * The POC subscribes to the global feed channel. Additional Social channels\n * can be added here without creating another WebSocket connection.\n */\nexport class SocialRealtimeService {\n readonly name = 'SocialRealtimeService' as const;\n\n readonly #messenger: BackendWebSocketServiceMessenger;\n\n readonly #listeners = new Set<SocialFeedEventListener>();\n\n readonly #reconnectListeners = new Set<SocialFeedReconnectListener>();\n\n readonly #isEnabled: () => boolean;\n\n #active = false;\n\n #subscription: WebSocketSubscription | undefined;\n\n #subscriptionPromise: Promise<void> | undefined;\n\n #wasDisconnected = false;\n\n constructor({\n messenger,\n isEnabled = (): boolean => true,\n }: SocialRealtimeServiceOptions) {\n this.#messenger = messenger;\n this.#isEnabled = isEnabled;\n\n this.#messenger.subscribe(\n 'BackendWebSocketService:connectionStateChanged',\n ({ state }: { state: WebSocketState }): void => {\n if (state === WebSocketState.DISCONNECTED) {\n this.#subscription = undefined;\n this.#wasDisconnected = true;\n }\n\n if (state === WebSocketState.CONNECTED && this.#active) {\n const isReconnect = this.#wasDisconnected;\n this.#wasDisconnected = false;\n // Subscription setup handles its own errors and must not block reconnect handling.\n // eslint-disable-next-line no-void\n void this.#subscribeToFeed();\n\n if (isReconnect) {\n this.#reconnectListeners.forEach((listener) => listener());\n }\n }\n },\n );\n }\n\n addListener(listener: SocialFeedEventListener): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n addReconnectListener(listener: SocialFeedReconnectListener): () => void {\n this.#reconnectListeners.add(listener);\n return () => this.#reconnectListeners.delete(listener);\n }\n\n async setActive(active: boolean): Promise<void> {\n this.#active = active && this.#isEnabled();\n\n if (!this.#active) {\n await this.#unsubscribeFromFeed();\n return;\n }\n\n await this.#subscribeToFeed();\n }\n\n async #subscribeToFeed(): Promise<void> {\n if (!this.#active || this.#subscription) {\n return;\n }\n\n while (this.#subscriptionPromise) {\n await this.#subscriptionPromise;\n\n if (!this.#active || this.#subscription) {\n return;\n }\n }\n\n const subscriptionPromise = Promise.resolve().then(\n async (): Promise<void> => {\n try {\n await this.#messenger.call('BackendWebSocketService:connect');\n\n // Each service needs its own callback and subscription lifecycle.\n const subscription = await this.#messenger.call(\n 'BackendWebSocketService:subscribe',\n {\n channels: [SOCIAL_FEED_CHANNEL],\n channelType: SOCIAL_FEED_CHANNEL_TYPE,\n callback: (notification: ServerNotificationMessage) => {\n this.#handleNotification(notification);\n },\n },\n );\n\n if (!this.#active) {\n await subscription.unsubscribe();\n return;\n }\n\n this.#subscription = subscription;\n } catch {\n this.#subscription = undefined;\n }\n },\n );\n this.#subscriptionPromise = subscriptionPromise;\n\n try {\n await subscriptionPromise;\n } finally {\n this.#subscriptionPromise = undefined;\n }\n }\n\n async #unsubscribeFromFeed(): Promise<void> {\n const subscription = this.#subscription;\n this.#subscription = undefined;\n\n if (subscription) {\n await subscription.unsubscribe();\n }\n }\n\n #handleNotification(notification: ServerNotificationMessage): void {\n if (notification.channel !== SOCIAL_FEED_CHANNEL) {\n return;\n }\n\n const event = parseSocialFeedEvent(notification.data);\n if (!event) {\n return;\n }\n\n this.#listeners.forEach((listener) => listener(event));\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export type { SocialServiceActions, SocialServiceEvents, SocialServiceMessenger,
5
5
  export { SocialService } from './SocialService.js';
6
6
  export type { SocialServiceFetchClosedPositionsAction, SocialServiceFetchFeedAction, SocialServiceFetchFollowersAction, SocialServiceFetchTokenFeedAction, SocialServiceFetchFollowingAction, SocialServiceFetchLeaderboardAction, SocialServiceFetchOpenPositionsAction, SocialServiceFetchPositionByIdAction, SocialServiceFetchTraderFeedAction, SocialServiceFetchTraderProfileAction, SocialServiceFollowAction, SocialServiceOptInToLeaderboardAction, SocialServiceOptOutOfLeaderboardAction, SocialServiceReactToCommentAction, SocialServiceCreateSwapCommentAction, SocialServiceRefreshNotificationPreferencesCacheAction, SocialServiceRemoveCommentReactionAction, SocialServiceUnfollowAction, } from './SocialService-method-action-types.js';
7
7
  export { TRADER_RANKING_TAGS, TradeStruct } from './social-types.js';
8
+ export { SOCIAL_FEED_CHANNEL, SOCIAL_FEED_CHANNEL_TYPE, SocialRealtimeService, } from './SocialRealtimeService.js';
9
+ export type { SocialFeedEvent, SocialFeedEventListener, SocialFeedReconnectListener, SocialRealtimeServiceOptions, } from './SocialRealtimeService.js';
8
10
  export type { AuthorComment, CommentEngagement, CommentReaction, CommentReactionProfile, CopytradedAllTime, CreateSwapCommentOptions, FeedActorSummary, FeedItem, FeedPagination, FeedResponse, FetchFeedOptions, FetchFollowersOptions, FetchTokenFeedOptions, FetchLeaderboardOptions, FetchPositionByIdOptions, FetchPositionsOptions, FetchTraderFeedOptions, FetchTraderProfileOptions, FollowersResponse, FollowingResponse, FollowOptions, FollowResponse, LeaderboardEntry, LeaderboardResponse, Pagination, PerChainBreakdown, Position, PositionsResponse, ProfileSummary, ReactToCommentOptions, RemoveCommentReactionOptions, SocialControllerState, SocialHandles, SwapCommentAuthor, SwapCommentResponse, TokenFeedChain, TokenFeedStatus, Trade, TradeAction, TradeInFlight, TraderProfile, TraderProfileResponse, TraderRankingTag, TraderStats, UnfollowOptions, UnfollowResponse, } from './social-types.js';
9
11
  export { serviceName as socialServiceName, SocialServiceErrorMessage, } from './social-constants.js';
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,EACzB,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,kCAAkC,EAClC,wCAAwC,EACxC,yCAAyC,EACzC,oCAAoC,EACpC,qCAAqC,EACrC,uCAAuC,GACxC,MAAM,2CAA2C,CAAC;AAEnD,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,YAAY,EACV,uCAAuC,EACvC,4BAA4B,EAC5B,iCAAiC,EACjC,iCAAiC,EACjC,iCAAiC,EACjC,mCAAmC,EACnC,qCAAqC,EACrC,oCAAoC,EACpC,kCAAkC,EAClC,qCAAqC,EACrC,yBAAyB,EACzB,qCAAqC,EACrC,sCAAsC,EACtC,iCAAiC,EACjC,oCAAoC,EACpC,sDAAsD,EACtD,wCAAwC,EACxC,2BAA2B,GAC5B,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,4BAA4B,EAC5B,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,KAAK,EACL,WAAW,EACX,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,IAAI,iBAAiB,EAChC,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,EACzB,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,kCAAkC,EAClC,wCAAwC,EACxC,yCAAyC,EACzC,oCAAoC,EACpC,qCAAqC,EACrC,uCAAuC,GACxC,MAAM,2CAA2C,CAAC;AAEnD,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,YAAY,EACV,uCAAuC,EACvC,4BAA4B,EAC5B,iCAAiC,EACjC,iCAAiC,EACjC,iCAAiC,EACjC,mCAAmC,EACnC,qCAAqC,EACrC,oCAAoC,EACpC,kCAAkC,EAClC,qCAAqC,EACrC,yBAAyB,EACzB,qCAAqC,EACrC,sCAAsC,EACtC,iCAAiC,EACjC,oCAAoC,EACpC,sDAAsD,EACtD,wCAAwC,EACxC,2BAA2B,GAC5B,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,iBAAiB,EACjB,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,4BAA4B,EAC5B,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,KAAK,EACL,WAAW,EACX,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,IAAI,iBAAiB,EAChC,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { SocialController, getDefaultSocialControllerState, } from './SocialController.js';
2
2
  export { SocialService } from './SocialService.js';
3
3
  export { TRADER_RANKING_TAGS, TradeStruct } from './social-types.js';
4
+ export { SOCIAL_FEED_CHANNEL, SOCIAL_FEED_CHANNEL_TYPE, SocialRealtimeService, } from './SocialRealtimeService.js';
4
5
  export { serviceName as socialServiceName, SocialServiceErrorMessage, } from './social-constants.js';
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,MAAM,uBAAuB,CAAC;AAgB/B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAuBnD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAkDrE,OAAO,EACL,WAAW,IAAI,iBAAiB,EAChC,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC","sourcesContent":["export type {\n SocialControllerActions,\n SocialControllerEvents,\n SocialControllerGetStateAction,\n SocialControllerMessenger,\n SocialControllerOptions,\n SocialControllerStateChangeEvent,\n} from './SocialController.js';\nexport {\n SocialController,\n getDefaultSocialControllerState,\n} from './SocialController.js';\n\nexport type {\n SocialControllerFollowTraderAction,\n SocialControllerOptInToLeaderboardAction,\n SocialControllerOptOutOfLeaderboardAction,\n SocialControllerUnfollowTraderAction,\n SocialControllerUpdateFollowingAction,\n SocialControllerUpdateLeaderboardAction,\n} from './SocialController-method-action-types.js';\n\nexport type {\n SocialServiceActions,\n SocialServiceEvents,\n SocialServiceMessenger,\n} from './SocialService.js';\nexport { SocialService } from './SocialService.js';\n\nexport type {\n SocialServiceFetchClosedPositionsAction,\n SocialServiceFetchFeedAction,\n SocialServiceFetchFollowersAction,\n SocialServiceFetchTokenFeedAction,\n SocialServiceFetchFollowingAction,\n SocialServiceFetchLeaderboardAction,\n SocialServiceFetchOpenPositionsAction,\n SocialServiceFetchPositionByIdAction,\n SocialServiceFetchTraderFeedAction,\n SocialServiceFetchTraderProfileAction,\n SocialServiceFollowAction,\n SocialServiceOptInToLeaderboardAction,\n SocialServiceOptOutOfLeaderboardAction,\n SocialServiceReactToCommentAction,\n SocialServiceCreateSwapCommentAction,\n SocialServiceRefreshNotificationPreferencesCacheAction,\n SocialServiceRemoveCommentReactionAction,\n SocialServiceUnfollowAction,\n} from './SocialService-method-action-types.js';\n\nexport { TRADER_RANKING_TAGS, TradeStruct } from './social-types.js';\nexport type {\n AuthorComment,\n CommentEngagement,\n CommentReaction,\n CommentReactionProfile,\n CopytradedAllTime,\n CreateSwapCommentOptions,\n FeedActorSummary,\n FeedItem,\n FeedPagination,\n FeedResponse,\n FetchFeedOptions,\n FetchFollowersOptions,\n FetchTokenFeedOptions,\n FetchLeaderboardOptions,\n FetchPositionByIdOptions,\n FetchPositionsOptions,\n FetchTraderFeedOptions,\n FetchTraderProfileOptions,\n FollowersResponse,\n FollowingResponse,\n FollowOptions,\n FollowResponse,\n LeaderboardEntry,\n LeaderboardResponse,\n Pagination,\n PerChainBreakdown,\n Position,\n PositionsResponse,\n ProfileSummary,\n ReactToCommentOptions,\n RemoveCommentReactionOptions,\n SocialControllerState,\n SocialHandles,\n SwapCommentAuthor,\n SwapCommentResponse,\n TokenFeedChain,\n TokenFeedStatus,\n Trade,\n TradeAction,\n TradeInFlight,\n TraderProfile,\n TraderProfileResponse,\n TraderRankingTag,\n TraderStats,\n UnfollowOptions,\n UnfollowResponse,\n} from './social-types.js';\n\nexport {\n serviceName as socialServiceName,\n SocialServiceErrorMessage,\n} from './social-constants.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,gBAAgB,EAChB,+BAA+B,GAChC,MAAM,uBAAuB,CAAC;AAgB/B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAuBnD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AAwDpC,OAAO,EACL,WAAW,IAAI,iBAAiB,EAChC,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC","sourcesContent":["export type {\n SocialControllerActions,\n SocialControllerEvents,\n SocialControllerGetStateAction,\n SocialControllerMessenger,\n SocialControllerOptions,\n SocialControllerStateChangeEvent,\n} from './SocialController.js';\nexport {\n SocialController,\n getDefaultSocialControllerState,\n} from './SocialController.js';\n\nexport type {\n SocialControllerFollowTraderAction,\n SocialControllerOptInToLeaderboardAction,\n SocialControllerOptOutOfLeaderboardAction,\n SocialControllerUnfollowTraderAction,\n SocialControllerUpdateFollowingAction,\n SocialControllerUpdateLeaderboardAction,\n} from './SocialController-method-action-types.js';\n\nexport type {\n SocialServiceActions,\n SocialServiceEvents,\n SocialServiceMessenger,\n} from './SocialService.js';\nexport { SocialService } from './SocialService.js';\n\nexport type {\n SocialServiceFetchClosedPositionsAction,\n SocialServiceFetchFeedAction,\n SocialServiceFetchFollowersAction,\n SocialServiceFetchTokenFeedAction,\n SocialServiceFetchFollowingAction,\n SocialServiceFetchLeaderboardAction,\n SocialServiceFetchOpenPositionsAction,\n SocialServiceFetchPositionByIdAction,\n SocialServiceFetchTraderFeedAction,\n SocialServiceFetchTraderProfileAction,\n SocialServiceFollowAction,\n SocialServiceOptInToLeaderboardAction,\n SocialServiceOptOutOfLeaderboardAction,\n SocialServiceReactToCommentAction,\n SocialServiceCreateSwapCommentAction,\n SocialServiceRefreshNotificationPreferencesCacheAction,\n SocialServiceRemoveCommentReactionAction,\n SocialServiceUnfollowAction,\n} from './SocialService-method-action-types.js';\n\nexport { TRADER_RANKING_TAGS, TradeStruct } from './social-types.js';\nexport {\n SOCIAL_FEED_CHANNEL,\n SOCIAL_FEED_CHANNEL_TYPE,\n SocialRealtimeService,\n} from './SocialRealtimeService.js';\nexport type {\n SocialFeedEvent,\n SocialFeedEventListener,\n SocialFeedReconnectListener,\n SocialRealtimeServiceOptions,\n} from './SocialRealtimeService.js';\nexport type {\n AuthorComment,\n CommentEngagement,\n CommentReaction,\n CommentReactionProfile,\n CopytradedAllTime,\n CreateSwapCommentOptions,\n FeedActorSummary,\n FeedItem,\n FeedPagination,\n FeedResponse,\n FetchFeedOptions,\n FetchFollowersOptions,\n FetchTokenFeedOptions,\n FetchLeaderboardOptions,\n FetchPositionByIdOptions,\n FetchPositionsOptions,\n FetchTraderFeedOptions,\n FetchTraderProfileOptions,\n FollowersResponse,\n FollowingResponse,\n FollowOptions,\n FollowResponse,\n LeaderboardEntry,\n LeaderboardResponse,\n Pagination,\n PerChainBreakdown,\n Position,\n PositionsResponse,\n ProfileSummary,\n ReactToCommentOptions,\n RemoveCommentReactionOptions,\n SocialControllerState,\n SocialHandles,\n SwapCommentAuthor,\n SwapCommentResponse,\n TokenFeedChain,\n TokenFeedStatus,\n Trade,\n TradeAction,\n TradeInFlight,\n TraderProfile,\n TraderProfileResponse,\n TraderRankingTag,\n TraderStats,\n UnfollowOptions,\n UnfollowResponse,\n} from './social-types.js';\n\nexport {\n serviceName as socialServiceName,\n SocialServiceErrorMessage,\n} from './social-constants.js';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/social-controllers",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "description": "A collection of social related controllers",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -39,10 +39,10 @@
39
39
  "build:only-clean": "rimraf './dist' './tsconfig.build.tsbuildinfo'",
40
40
  "changelog:update": "../../scripts/update-changelog.sh @metamask/social-controllers",
41
41
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/social-controllers",
42
- "lint:tsconfigs": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts",
43
- "lint:tsconfigs:fix": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts --fix",
44
- "messenger-action-types:check": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --esm --check",
45
- "messenger-action-types:generate": "tsx ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --esm --generate",
42
+ "lint:tsconfigs": "node --import ../../scripts/resolver/register.ts --experimental-transform-types ../../scripts/lint-tsconfigs/lint-tsconfigs.ts",
43
+ "lint:tsconfigs:fix": "node --import ../../scripts/resolver/register.ts --experimental-transform-types ../../scripts/lint-tsconfigs/lint-tsconfigs.ts --fix",
44
+ "messenger-action-types:check": "node --import ../../scripts/resolver/register.ts --experimental-transform-types ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --esm --check",
45
+ "messenger-action-types:generate": "node --import ../../scripts/resolver/register.ts --experimental-transform-types ../../packages/messenger-cli/src/cli.ts --formatter oxfmt --esm --generate",
46
46
  "since-latest-release": "../../scripts/since-latest-release.sh",
47
47
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter",
48
48
  "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache",
@@ -51,8 +51,9 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@metamask/base-controller": "^10.0.0",
54
- "@metamask/base-data-service": "^2.0.0",
54
+ "@metamask/base-data-service": "^2.1.0",
55
55
  "@metamask/controller-utils": "^13.0.0",
56
+ "@metamask/core-backend": "^12.0.0",
56
57
  "@metamask/messenger": "^3.0.0",
57
58
  "@metamask/profile-sync-controller": "^33.0.0",
58
59
  "@metamask/superstruct": "^3.4.1"
@@ -62,10 +63,9 @@
62
63
  "@types/jest": "^30.0.0",
63
64
  "@typescript/native": "npm:typescript@^7.0.2",
64
65
  "deepmerge": "^4.3.1",
65
- "jest": "^30.4.2",
66
+ "jest": "^30.5.2",
66
67
  "rimraf": "^6.1.3",
67
- "ts-jest": "^29.4.12",
68
- "tsx": "^4.23.15",
68
+ "ts-jest": "^29.4.14",
69
69
  "typedoc": "^0.25.13",
70
70
  "typedoc-plugin-missing-exports": "^2.0.0",
71
71
  "typescript": "npm:@typescript/typescript6@^6.0.2"