@hybrd/xmtp 1.0.0 → 1.0.3
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/.cache/tsbuildinfo.json +1 -1
- package/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-lint$colon$fix.log +6 -0
- package/dist/scripts/generate-keys.d.ts +1 -0
- package/dist/scripts/generate-keys.js +19 -0
- package/dist/scripts/refresh-identity.d.ts +1 -0
- package/dist/scripts/refresh-identity.js +93 -0
- package/dist/scripts/register-wallet.d.ts +1 -0
- package/dist/scripts/register-wallet.js +75 -0
- package/dist/scripts/revoke-all-installations.d.ts +2 -0
- package/dist/scripts/revoke-all-installations.js +68 -0
- package/dist/scripts/revoke-installations.d.ts +2 -0
- package/dist/scripts/revoke-installations.js +62 -0
- package/dist/src/abi/l2_resolver.d.ts +992 -0
- package/dist/src/abi/l2_resolver.js +699 -0
- package/dist/src/client.d.ts +76 -0
- package/dist/src/client.js +709 -0
- package/dist/src/constants.d.ts +3 -0
- package/dist/src/constants.js +6 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.js +46 -0
- package/dist/src/lib/message-listener.d.ts +69 -0
- package/dist/src/lib/message-listener.js +235 -0
- package/dist/src/lib/message-listener.test.d.ts +1 -0
- package/dist/src/lib/message-listener.test.js +303 -0
- package/dist/src/lib/subjects.d.ts +24 -0
- package/dist/src/lib/subjects.js +68 -0
- package/dist/src/resolver/address-resolver.d.ts +57 -0
- package/dist/src/resolver/address-resolver.js +168 -0
- package/dist/src/resolver/basename-resolver.d.ts +134 -0
- package/dist/src/resolver/basename-resolver.js +409 -0
- package/dist/src/resolver/ens-resolver.d.ts +95 -0
- package/dist/src/resolver/ens-resolver.js +249 -0
- package/dist/src/resolver/index.d.ts +1 -0
- package/dist/src/resolver/index.js +1 -0
- package/dist/src/resolver/resolver.d.ts +162 -0
- package/dist/src/resolver/resolver.js +238 -0
- package/dist/src/resolver/xmtp-resolver.d.ts +95 -0
- package/dist/src/resolver/xmtp-resolver.js +297 -0
- package/dist/src/service-client.d.ts +77 -0
- package/dist/src/service-client.js +198 -0
- package/dist/src/types.d.ts +123 -0
- package/dist/src/types.js +5 -0
- package/package.json +5 -4
- package/tsconfig.json +3 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// ===================================================================
|
|
2
|
+
// Betting Configuration
|
|
3
|
+
// ===================================================================
|
|
4
|
+
export const DEFAULT_OPTIONS = ["yes", "no"];
|
|
5
|
+
export const DEFAULT_AMOUNT = "0.1";
|
|
6
|
+
export const MAX_USDC_AMOUNT = 10; // Maximum allowed USDC transaction amount
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export * from "./client";
|
|
2
|
+
export * from "./constants";
|
|
3
|
+
export * from "./lib/message-listener";
|
|
4
|
+
export * from "./lib/subjects";
|
|
5
|
+
export * from "./resolver";
|
|
6
|
+
export * from "./resolver/basename-resolver";
|
|
7
|
+
export * from "./resolver/ens-resolver";
|
|
8
|
+
export * from "./resolver/xmtp-resolver";
|
|
9
|
+
export * from "./service-client";
|
|
10
|
+
export * from "./types";
|
|
11
|
+
export { createXMTPConnectionManager, XMTPConnectionManager, type XMTPConnectionConfig, type XMTPConnectionHealth } from "./client";
|
|
12
|
+
export { createXmtpServiceClient, XmtpServiceClient } from "./service-client";
|
|
13
|
+
export type { GetMessageParams, GetRootMessageParams, SendMessageParams, SendMessageResponse, SendReactionParams, SendReactionResponse, SendReplyParams, SendReplyResponse, SendTransactionParams, SendTransactionResponse, TransactionCall, TransactionRequest, XmtpRootMessageResponse, XmtpServiceClientConfig, XmtpServiceMessage, XmtpServiceResponse } from "./types";
|
|
14
|
+
export { Client, IdentifierKind, type DecodedMessage, type Dm, type LogLevel, type Signer, type XmtpEnv } from "@xmtp/node-sdk";
|
|
15
|
+
export { ContentTypeTransactionReference, type TransactionReference } from "@xmtp/content-type-transaction-reference";
|
|
16
|
+
export { ContentTypeText, type TextParameters } from "@xmtp/content-type-text";
|
|
17
|
+
export { ContentTypeReaction, type Reaction } from "@xmtp/content-type-reaction";
|
|
18
|
+
export { ContentTypeReply, ReplyCodec, type Reply } from "@xmtp/content-type-reply";
|
|
19
|
+
export { ContentTypeGroupUpdated, GroupUpdatedCodec, type GroupUpdated } from "@xmtp/content-type-group-updated";
|
|
20
|
+
export { ContentTypeWalletSendCalls, type WalletSendCallsParams } from "@xmtp/content-type-wallet-send-calls";
|
|
21
|
+
export { backupDbToPersistentStorage, createSigner, createUser, createXMTPClient, diagnoseXMTPIdentityIssue, generateEncryptionKeyHex, getEncryptionKeyFromHex, logAgentDetails, startPeriodicBackup, validateEnvironment } from "./client";
|
|
22
|
+
export { DEFAULT_AMOUNT, DEFAULT_OPTIONS, MAX_USDC_AMOUNT } from "./constants";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// ===================================================================
|
|
2
|
+
// XMTP Package - Main Entry Point
|
|
3
|
+
// ===================================================================
|
|
4
|
+
// This package provides a clean interface to XMTP functionality
|
|
5
|
+
// Re-exports core XMTP SDK types and utilities
|
|
6
|
+
export * from "./client";
|
|
7
|
+
export * from "./constants";
|
|
8
|
+
export * from "./lib/message-listener";
|
|
9
|
+
export * from "./lib/subjects";
|
|
10
|
+
export * from "./resolver";
|
|
11
|
+
export * from "./resolver/basename-resolver";
|
|
12
|
+
export * from "./resolver/ens-resolver";
|
|
13
|
+
export * from "./resolver/xmtp-resolver";
|
|
14
|
+
export * from "./service-client";
|
|
15
|
+
export * from "./types";
|
|
16
|
+
// ===================================================================
|
|
17
|
+
// Enhanced XMTP Client & Connection Management
|
|
18
|
+
// ===================================================================
|
|
19
|
+
export { createXMTPConnectionManager,
|
|
20
|
+
// Enhanced connection management
|
|
21
|
+
XMTPConnectionManager } from "./client";
|
|
22
|
+
// ===================================================================
|
|
23
|
+
// XMTP Service Client (for external service communication)
|
|
24
|
+
// ===================================================================
|
|
25
|
+
export { createXmtpServiceClient, XmtpServiceClient } from "./service-client";
|
|
26
|
+
// ===================================================================
|
|
27
|
+
// XMTP Core SDK Exports
|
|
28
|
+
// ===================================================================
|
|
29
|
+
export { Client } from "@xmtp/node-sdk";
|
|
30
|
+
// ===================================================================
|
|
31
|
+
// XMTP Content Types
|
|
32
|
+
// ===================================================================
|
|
33
|
+
export { ContentTypeTransactionReference } from "@xmtp/content-type-transaction-reference";
|
|
34
|
+
export { ContentTypeText } from "@xmtp/content-type-text";
|
|
35
|
+
export { ContentTypeReaction } from "@xmtp/content-type-reaction";
|
|
36
|
+
export { ContentTypeReply, ReplyCodec } from "@xmtp/content-type-reply";
|
|
37
|
+
export { ContentTypeGroupUpdated, GroupUpdatedCodec } from "@xmtp/content-type-group-updated";
|
|
38
|
+
export { ContentTypeWalletSendCalls } from "@xmtp/content-type-wallet-send-calls";
|
|
39
|
+
// ===================================================================
|
|
40
|
+
// Local Client Utilities
|
|
41
|
+
// ===================================================================
|
|
42
|
+
export { backupDbToPersistentStorage, createSigner, createUser, createXMTPClient, diagnoseXMTPIdentityIssue, generateEncryptionKeyHex, getEncryptionKeyFromHex, logAgentDetails, startPeriodicBackup, validateEnvironment } from "./client";
|
|
43
|
+
// ===================================================================
|
|
44
|
+
// Application Constants
|
|
45
|
+
// ===================================================================
|
|
46
|
+
export { DEFAULT_AMOUNT, DEFAULT_OPTIONS, MAX_USDC_AMOUNT } from "./constants";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { PublicClient } from "viem";
|
|
3
|
+
import type { MessageEvent, XmtpClient } from "../types";
|
|
4
|
+
export interface MessageListenerConfig {
|
|
5
|
+
publicClient: PublicClient;
|
|
6
|
+
xmtpClient: XmtpClient;
|
|
7
|
+
/**
|
|
8
|
+
* Filter function to determine which messages to process
|
|
9
|
+
* Return true to process the message, false to skip
|
|
10
|
+
*/
|
|
11
|
+
filter?: (event: Pick<MessageEvent, "conversation" | "message" | "rootMessage">) => Promise<boolean> | boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Heartbeat interval in milliseconds (default: 5 minutes)
|
|
14
|
+
*/
|
|
15
|
+
heartbeatInterval?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Conversation check interval in milliseconds (default: 30 seconds)
|
|
18
|
+
*/
|
|
19
|
+
conversationCheckInterval?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Environment variable key for XMTP environment (default: "XMTP_ENV")
|
|
22
|
+
*/
|
|
23
|
+
envKey?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface MessageListenerEvents {
|
|
26
|
+
message: [data: MessageEvent];
|
|
27
|
+
error: [error: Error];
|
|
28
|
+
started: [];
|
|
29
|
+
stopped: [];
|
|
30
|
+
heartbeat: [stats: {
|
|
31
|
+
messageCount: number;
|
|
32
|
+
conversationCount: number;
|
|
33
|
+
}];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A flexible XMTP message listener that can be configured for different applications
|
|
37
|
+
*/
|
|
38
|
+
export declare class MessageListener extends EventEmitter {
|
|
39
|
+
private xmtpClient;
|
|
40
|
+
private resolver;
|
|
41
|
+
private filter?;
|
|
42
|
+
private heartbeatInterval?;
|
|
43
|
+
private fallbackCheckInterval?;
|
|
44
|
+
private messageCount;
|
|
45
|
+
private conversations;
|
|
46
|
+
private readonly config;
|
|
47
|
+
constructor(config: MessageListenerConfig);
|
|
48
|
+
on<U extends keyof MessageListenerEvents>(event: U, listener: (...args: MessageListenerEvents[U]) => void): this;
|
|
49
|
+
emit<U extends keyof MessageListenerEvents>(event: U, ...args: MessageListenerEvents[U]): boolean;
|
|
50
|
+
start(): Promise<void>;
|
|
51
|
+
private cleanup;
|
|
52
|
+
stop(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Get current statistics
|
|
55
|
+
*/
|
|
56
|
+
getStats(): {
|
|
57
|
+
messageCount: number;
|
|
58
|
+
conversationCount: number;
|
|
59
|
+
isActive: boolean;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper function to start a message listener
|
|
64
|
+
*/
|
|
65
|
+
export declare function startMessageListener(config: MessageListenerConfig): Promise<MessageListener>;
|
|
66
|
+
/**
|
|
67
|
+
* Factory function to create a message listener with common filters
|
|
68
|
+
*/
|
|
69
|
+
export declare function createMessageListener(config: MessageListenerConfig): MessageListener;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { http, createPublicClient } from "viem";
|
|
3
|
+
import { mainnet } from "viem/chains";
|
|
4
|
+
import { Resolver } from "../resolver/resolver";
|
|
5
|
+
/**
|
|
6
|
+
* A flexible XMTP message listener that can be configured for different applications
|
|
7
|
+
*/
|
|
8
|
+
export class MessageListener extends EventEmitter {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super();
|
|
11
|
+
this.messageCount = 0;
|
|
12
|
+
this.conversations = [];
|
|
13
|
+
this.xmtpClient = config.xmtpClient;
|
|
14
|
+
// Create mainnet client for ENS resolution
|
|
15
|
+
const mainnetClient = createPublicClient({
|
|
16
|
+
chain: mainnet,
|
|
17
|
+
transport: http()
|
|
18
|
+
});
|
|
19
|
+
// Create unified resolver with all capabilities
|
|
20
|
+
this.resolver = new Resolver({
|
|
21
|
+
xmtpClient: this.xmtpClient,
|
|
22
|
+
mainnetClient,
|
|
23
|
+
baseClient: config.publicClient,
|
|
24
|
+
maxCacheSize: 1000,
|
|
25
|
+
cacheTtl: 86400000 // 24 hours
|
|
26
|
+
});
|
|
27
|
+
this.filter = config.filter;
|
|
28
|
+
this.config = {
|
|
29
|
+
heartbeatInterval: config.heartbeatInterval ?? 300000, // 5 minutes
|
|
30
|
+
conversationCheckInterval: config.conversationCheckInterval ?? 30000, // 30 seconds
|
|
31
|
+
envKey: config.envKey ?? "XMTP_ENV"
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Type-safe event emitter methods
|
|
35
|
+
on(event, listener) {
|
|
36
|
+
return super.on(event, listener);
|
|
37
|
+
}
|
|
38
|
+
emit(event, ...args) {
|
|
39
|
+
return super.emit(event, ...args);
|
|
40
|
+
}
|
|
41
|
+
async start() {
|
|
42
|
+
const XMTP_ENV = process.env[this.config.envKey];
|
|
43
|
+
// Pre-populate address cache from existing conversations
|
|
44
|
+
await this.resolver?.prePopulateAllCaches();
|
|
45
|
+
console.log("📡 Syncing conversations...");
|
|
46
|
+
await this.xmtpClient.conversations.sync();
|
|
47
|
+
const address = this.xmtpClient.accountIdentifier?.identifier;
|
|
48
|
+
// List existing conversations for debugging
|
|
49
|
+
this.conversations = await this.xmtpClient.conversations.list();
|
|
50
|
+
console.log(`🤖 XMTP[${XMTP_ENV}] Listening on ${address} ...`);
|
|
51
|
+
// Emit started event
|
|
52
|
+
this.emit("started");
|
|
53
|
+
// Stream all messages and emit events for processing
|
|
54
|
+
try {
|
|
55
|
+
const stream = await this.xmtpClient.conversations.streamAllMessages();
|
|
56
|
+
// Add a heartbeat to show the listener is active
|
|
57
|
+
this.heartbeatInterval = setInterval(() => {
|
|
58
|
+
this.emit("heartbeat", {
|
|
59
|
+
messageCount: this.messageCount,
|
|
60
|
+
conversationCount: this.conversations.length
|
|
61
|
+
});
|
|
62
|
+
if (this.messageCount > 0) {
|
|
63
|
+
console.log(`💓 Active - processed ${this.messageCount} messages`);
|
|
64
|
+
}
|
|
65
|
+
}, this.config.heartbeatInterval);
|
|
66
|
+
// Check for new conversations
|
|
67
|
+
this.fallbackCheckInterval = setInterval(async () => {
|
|
68
|
+
try {
|
|
69
|
+
const latestConversations = await this.xmtpClient.conversations.list();
|
|
70
|
+
if (latestConversations.length > this.conversations.length) {
|
|
71
|
+
console.log(`🆕 Detected ${latestConversations.length - this.conversations.length} new conversations`);
|
|
72
|
+
this.conversations.push(...latestConversations.slice(this.conversations.length));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error("❌ Error checking for new conversations:", error);
|
|
77
|
+
this.emit("error", error);
|
|
78
|
+
}
|
|
79
|
+
}, this.config.conversationCheckInterval);
|
|
80
|
+
try {
|
|
81
|
+
for await (const message of stream) {
|
|
82
|
+
this.messageCount++;
|
|
83
|
+
try {
|
|
84
|
+
// Skip messages from self or null messages
|
|
85
|
+
if (!message ||
|
|
86
|
+
message.senderInboxId.toLowerCase() ===
|
|
87
|
+
this.xmtpClient.inboxId.toLowerCase()) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
console.log(`📨 Received message "${JSON.stringify(message)}" in ${message.conversationId}`);
|
|
91
|
+
// Get conversation details
|
|
92
|
+
const conversation = await this.xmtpClient.conversations.getConversationById(message.conversationId);
|
|
93
|
+
if (!conversation) {
|
|
94
|
+
console.log("❌ Could not find conversation for message");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const contentTypeId = message.contentType?.typeId;
|
|
98
|
+
// Extract message content for processing
|
|
99
|
+
let messageContent;
|
|
100
|
+
if (contentTypeId === "reply") {
|
|
101
|
+
const replyContent = message.content;
|
|
102
|
+
messageContent = (replyContent?.content || "").toString();
|
|
103
|
+
}
|
|
104
|
+
else if (contentTypeId === "remoteStaticAttachment" ||
|
|
105
|
+
contentTypeId === "attachment") {
|
|
106
|
+
// For attachments, use the fallback message or filename
|
|
107
|
+
messageContent =
|
|
108
|
+
message.fallback ||
|
|
109
|
+
message.content?.filename ||
|
|
110
|
+
"[Attachment]";
|
|
111
|
+
}
|
|
112
|
+
else if (contentTypeId === "reaction") {
|
|
113
|
+
// For reactions, use a simple representation
|
|
114
|
+
const reactionContent = message.content;
|
|
115
|
+
messageContent = `[Reaction: ${reactionContent.content || ""}]`;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// For text and other content types, safely convert to string
|
|
119
|
+
messageContent = message.content ? String(message.content) : "";
|
|
120
|
+
}
|
|
121
|
+
// Find root message for replies and reactions
|
|
122
|
+
let rootMessage = message;
|
|
123
|
+
let parentMessage = null;
|
|
124
|
+
if (contentTypeId === "reply") {
|
|
125
|
+
const { reference } = message.content;
|
|
126
|
+
rootMessage = await this.resolver.findRootMessage(reference);
|
|
127
|
+
parentMessage = await this.resolver.findMessage(reference);
|
|
128
|
+
}
|
|
129
|
+
else if (contentTypeId === "reaction") {
|
|
130
|
+
const { reference } = message.content;
|
|
131
|
+
rootMessage = await this.resolver.findRootMessage(reference);
|
|
132
|
+
parentMessage = await this.resolver.findMessage(reference);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// For text messages and attachments, they are root messages
|
|
136
|
+
rootMessage = message;
|
|
137
|
+
parentMessage = null;
|
|
138
|
+
}
|
|
139
|
+
// Skip if we couldn't find the root message
|
|
140
|
+
if (!rootMessage) {
|
|
141
|
+
console.warn(`⚠️ [MessageListener] Could not find root message for: ${message.id}`);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// Apply custom message filter if provided
|
|
145
|
+
if (this.filter) {
|
|
146
|
+
const shouldProcess = await this.filter({
|
|
147
|
+
conversation,
|
|
148
|
+
message,
|
|
149
|
+
rootMessage
|
|
150
|
+
});
|
|
151
|
+
if (!shouldProcess) {
|
|
152
|
+
console.log("🔄 Skipping message:", message.id);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Create sender using unified resolver
|
|
157
|
+
const sender = await this.resolver.createXmtpSender(message.senderInboxId, message.conversationId);
|
|
158
|
+
// Extract and resolve subjects (basenames and ENS names mentioned in message)
|
|
159
|
+
// TODO: Update extractSubjects to work with unified resolver
|
|
160
|
+
const subjects = {};
|
|
161
|
+
// Create enriched message with resolved address, name, subjects, root message, and parent message
|
|
162
|
+
const messageEvent = {
|
|
163
|
+
conversation,
|
|
164
|
+
message,
|
|
165
|
+
rootMessage: rootMessage, // We already checked it's not null above
|
|
166
|
+
parentMessage: parentMessage || undefined,
|
|
167
|
+
sender,
|
|
168
|
+
subjects
|
|
169
|
+
};
|
|
170
|
+
// Emit the enriched message
|
|
171
|
+
this.emit("message", messageEvent);
|
|
172
|
+
}
|
|
173
|
+
catch (messageError) {
|
|
174
|
+
console.error("❌ Error processing message:", messageError);
|
|
175
|
+
this.emit("error", messageError);
|
|
176
|
+
// Continue processing other messages instead of crashing
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch (streamError) {
|
|
181
|
+
console.error("❌ Error in message stream:", streamError);
|
|
182
|
+
this.cleanup();
|
|
183
|
+
this.emit("error", streamError);
|
|
184
|
+
console.log("🔄 Attempting to restart stream...");
|
|
185
|
+
// Wait a bit before restarting to avoid tight restart loops
|
|
186
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
187
|
+
// Recursively restart the message listener
|
|
188
|
+
return this.start();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (streamSetupError) {
|
|
192
|
+
console.error("❌ Error setting up message stream:", streamSetupError);
|
|
193
|
+
this.emit("error", streamSetupError);
|
|
194
|
+
throw streamSetupError;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
cleanup() {
|
|
198
|
+
if (this.heartbeatInterval) {
|
|
199
|
+
clearInterval(this.heartbeatInterval);
|
|
200
|
+
}
|
|
201
|
+
if (this.fallbackCheckInterval) {
|
|
202
|
+
clearInterval(this.fallbackCheckInterval);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
stop() {
|
|
206
|
+
this.cleanup();
|
|
207
|
+
this.emit("stopped");
|
|
208
|
+
console.log("🛑 Message listener stopped");
|
|
209
|
+
this.removeAllListeners();
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get current statistics
|
|
213
|
+
*/
|
|
214
|
+
getStats() {
|
|
215
|
+
return {
|
|
216
|
+
messageCount: this.messageCount,
|
|
217
|
+
conversationCount: this.conversations.length,
|
|
218
|
+
isActive: !!this.heartbeatInterval
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Helper function to start a message listener
|
|
224
|
+
*/
|
|
225
|
+
export async function startMessageListener(config) {
|
|
226
|
+
const listener = new MessageListener(config);
|
|
227
|
+
await listener.start();
|
|
228
|
+
return listener;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Factory function to create a message listener with common filters
|
|
232
|
+
*/
|
|
233
|
+
export function createMessageListener(config) {
|
|
234
|
+
return new MessageListener(config);
|
|
235
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|