@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.
Files changed (45) hide show
  1. package/.cache/tsbuildinfo.json +1 -1
  2. package/.turbo/turbo-build.log +5 -0
  3. package/.turbo/turbo-lint$colon$fix.log +6 -0
  4. package/dist/scripts/generate-keys.d.ts +1 -0
  5. package/dist/scripts/generate-keys.js +19 -0
  6. package/dist/scripts/refresh-identity.d.ts +1 -0
  7. package/dist/scripts/refresh-identity.js +93 -0
  8. package/dist/scripts/register-wallet.d.ts +1 -0
  9. package/dist/scripts/register-wallet.js +75 -0
  10. package/dist/scripts/revoke-all-installations.d.ts +2 -0
  11. package/dist/scripts/revoke-all-installations.js +68 -0
  12. package/dist/scripts/revoke-installations.d.ts +2 -0
  13. package/dist/scripts/revoke-installations.js +62 -0
  14. package/dist/src/abi/l2_resolver.d.ts +992 -0
  15. package/dist/src/abi/l2_resolver.js +699 -0
  16. package/dist/src/client.d.ts +76 -0
  17. package/dist/src/client.js +709 -0
  18. package/dist/src/constants.d.ts +3 -0
  19. package/dist/src/constants.js +6 -0
  20. package/dist/src/index.d.ts +22 -0
  21. package/dist/src/index.js +46 -0
  22. package/dist/src/lib/message-listener.d.ts +69 -0
  23. package/dist/src/lib/message-listener.js +235 -0
  24. package/dist/src/lib/message-listener.test.d.ts +1 -0
  25. package/dist/src/lib/message-listener.test.js +303 -0
  26. package/dist/src/lib/subjects.d.ts +24 -0
  27. package/dist/src/lib/subjects.js +68 -0
  28. package/dist/src/resolver/address-resolver.d.ts +57 -0
  29. package/dist/src/resolver/address-resolver.js +168 -0
  30. package/dist/src/resolver/basename-resolver.d.ts +134 -0
  31. package/dist/src/resolver/basename-resolver.js +409 -0
  32. package/dist/src/resolver/ens-resolver.d.ts +95 -0
  33. package/dist/src/resolver/ens-resolver.js +249 -0
  34. package/dist/src/resolver/index.d.ts +1 -0
  35. package/dist/src/resolver/index.js +1 -0
  36. package/dist/src/resolver/resolver.d.ts +162 -0
  37. package/dist/src/resolver/resolver.js +238 -0
  38. package/dist/src/resolver/xmtp-resolver.d.ts +95 -0
  39. package/dist/src/resolver/xmtp-resolver.js +297 -0
  40. package/dist/src/service-client.d.ts +77 -0
  41. package/dist/src/service-client.js +198 -0
  42. package/dist/src/types.d.ts +123 -0
  43. package/dist/src/types.js +5 -0
  44. package/package.json +5 -4
  45. package/tsconfig.json +3 -1
@@ -0,0 +1,3 @@
1
+ export declare const DEFAULT_OPTIONS: string[];
2
+ export declare const DEFAULT_AMOUNT = "0.1";
3
+ export declare const MAX_USDC_AMOUNT = 10;
@@ -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 {};