@azeth/sdk 0.2.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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/account/balance.d.ts +41 -0
  4. package/dist/account/balance.d.ts.map +1 -0
  5. package/dist/account/balance.js +264 -0
  6. package/dist/account/balance.js.map +1 -0
  7. package/dist/account/create.d.ts +27 -0
  8. package/dist/account/create.d.ts.map +1 -0
  9. package/dist/account/create.js +116 -0
  10. package/dist/account/create.js.map +1 -0
  11. package/dist/account/deposit.d.ts +34 -0
  12. package/dist/account/deposit.d.ts.map +1 -0
  13. package/dist/account/deposit.js +88 -0
  14. package/dist/account/deposit.js.map +1 -0
  15. package/dist/account/guardian-approval.d.ts +111 -0
  16. package/dist/account/guardian-approval.d.ts.map +1 -0
  17. package/dist/account/guardian-approval.js +223 -0
  18. package/dist/account/guardian-approval.js.map +1 -0
  19. package/dist/account/guardian.d.ts +27 -0
  20. package/dist/account/guardian.d.ts.map +1 -0
  21. package/dist/account/guardian.js +67 -0
  22. package/dist/account/guardian.js.map +1 -0
  23. package/dist/account/history.d.ts +22 -0
  24. package/dist/account/history.d.ts.map +1 -0
  25. package/dist/account/history.js +144 -0
  26. package/dist/account/history.js.map +1 -0
  27. package/dist/account/transfer.d.ts +28 -0
  28. package/dist/account/transfer.d.ts.map +1 -0
  29. package/dist/account/transfer.js +137 -0
  30. package/dist/account/transfer.js.map +1 -0
  31. package/dist/auth/erc8128.d.ts +14 -0
  32. package/dist/auth/erc8128.d.ts.map +1 -0
  33. package/dist/auth/erc8128.js +92 -0
  34. package/dist/auth/erc8128.js.map +1 -0
  35. package/dist/client.d.ts +394 -0
  36. package/dist/client.d.ts.map +1 -0
  37. package/dist/client.js +970 -0
  38. package/dist/client.js.map +1 -0
  39. package/dist/events/emitter.d.ts +96 -0
  40. package/dist/events/emitter.d.ts.map +1 -0
  41. package/dist/events/emitter.js +90 -0
  42. package/dist/events/emitter.js.map +1 -0
  43. package/dist/index.d.ts +29 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +33 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/messaging/message-router.d.ts +69 -0
  48. package/dist/messaging/message-router.d.ts.map +1 -0
  49. package/dist/messaging/message-router.js +307 -0
  50. package/dist/messaging/message-router.js.map +1 -0
  51. package/dist/messaging/rate-limiter.d.ts +31 -0
  52. package/dist/messaging/rate-limiter.d.ts.map +1 -0
  53. package/dist/messaging/rate-limiter.js +74 -0
  54. package/dist/messaging/rate-limiter.js.map +1 -0
  55. package/dist/messaging/xmtp.d.ts +144 -0
  56. package/dist/messaging/xmtp.d.ts.map +1 -0
  57. package/dist/messaging/xmtp.js +473 -0
  58. package/dist/messaging/xmtp.js.map +1 -0
  59. package/dist/payments/agreements.d.ts +87 -0
  60. package/dist/payments/agreements.d.ts.map +1 -0
  61. package/dist/payments/agreements.js +337 -0
  62. package/dist/payments/agreements.js.map +1 -0
  63. package/dist/payments/budget.d.ts +118 -0
  64. package/dist/payments/budget.d.ts.map +1 -0
  65. package/dist/payments/budget.js +176 -0
  66. package/dist/payments/budget.js.map +1 -0
  67. package/dist/payments/smart-fetch.d.ts +65 -0
  68. package/dist/payments/smart-fetch.d.ts.map +1 -0
  69. package/dist/payments/smart-fetch.js +115 -0
  70. package/dist/payments/smart-fetch.js.map +1 -0
  71. package/dist/payments/x402.d.ts +89 -0
  72. package/dist/payments/x402.d.ts.map +1 -0
  73. package/dist/payments/x402.js +620 -0
  74. package/dist/payments/x402.js.map +1 -0
  75. package/dist/registry/discover.d.ts +43 -0
  76. package/dist/registry/discover.d.ts.map +1 -0
  77. package/dist/registry/discover.js +272 -0
  78. package/dist/registry/discover.js.map +1 -0
  79. package/dist/registry/register.d.ts +44 -0
  80. package/dist/registry/register.d.ts.map +1 -0
  81. package/dist/registry/register.js +126 -0
  82. package/dist/registry/register.js.map +1 -0
  83. package/dist/reputation/opinion.d.ts +52 -0
  84. package/dist/reputation/opinion.d.ts.map +1 -0
  85. package/dist/reputation/opinion.js +198 -0
  86. package/dist/reputation/opinion.js.map +1 -0
  87. package/dist/utils/addresses.d.ts +6 -0
  88. package/dist/utils/addresses.d.ts.map +1 -0
  89. package/dist/utils/addresses.js +53 -0
  90. package/dist/utils/addresses.js.map +1 -0
  91. package/dist/utils/errors.d.ts +23 -0
  92. package/dist/utils/errors.d.ts.map +1 -0
  93. package/dist/utils/errors.js +188 -0
  94. package/dist/utils/errors.js.map +1 -0
  95. package/dist/utils/execution.d.ts +20 -0
  96. package/dist/utils/execution.d.ts.map +1 -0
  97. package/dist/utils/execution.js +28 -0
  98. package/dist/utils/execution.js.map +1 -0
  99. package/dist/utils/paymaster.d.ts +35 -0
  100. package/dist/utils/paymaster.d.ts.map +1 -0
  101. package/dist/utils/paymaster.js +115 -0
  102. package/dist/utils/paymaster.js.map +1 -0
  103. package/dist/utils/retry.d.ts +19 -0
  104. package/dist/utils/retry.d.ts.map +1 -0
  105. package/dist/utils/retry.js +68 -0
  106. package/dist/utils/retry.js.map +1 -0
  107. package/dist/utils/userop.d.ts +55 -0
  108. package/dist/utils/userop.d.ts.map +1 -0
  109. package/dist/utils/userop.js +201 -0
  110. package/dist/utils/userop.js.map +1 -0
  111. package/dist/utils/validation.d.ts +8 -0
  112. package/dist/utils/validation.d.ts.map +1 -0
  113. package/dist/utils/validation.js +35 -0
  114. package/dist/utils/validation.js.map +1 -0
  115. package/package.json +63 -0
@@ -0,0 +1,473 @@
1
+ import crypto from 'node:crypto';
2
+ import { AzethError, } from '@azeth/common';
3
+ import { RateLimiter } from './rate-limiter.js';
4
+ /** XMTP messaging client backed by @xmtp/agent-sdk.
5
+ *
6
+ * Provides E2E encrypted agent-to-agent messaging via the XMTP network.
7
+ * Messages are rate-limited per sender and reachability results are cached.
8
+ */
9
+ export class XMTPClient {
10
+ // We use `any` for the agent SDK types because they are imported dynamically
11
+ // and declaring full type stubs would be fragile. The public API is fully typed.
12
+ _agent = null;
13
+ /** Static Client class from @xmtp/agent-sdk, used for fetchInboxStates.
14
+ * The Agent's client instance doesn't expose this method, so we use the static version. */
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ _ClientClass = null;
17
+ _xmtpEnv = 'production';
18
+ _handlers = [];
19
+ _rateLimiter = null;
20
+ _reachabilityCache = new Map();
21
+ _reachabilityCacheTtlMs = 300_000; // 5 minutes default
22
+ _maxMessageLength = 10_000;
23
+ _ready = false;
24
+ _listening = false;
25
+ _messageStreamAbort = null;
26
+ _convStreamAbort = null;
27
+ _messageRouter = null;
28
+ _autoReply = false;
29
+ /** Initialize the XMTP client with a private key.
30
+ *
31
+ * Creates an XMTP Agent using the provided private key and config.
32
+ * Must be called before any messaging operations.
33
+ *
34
+ * @param privateKey - Owner's private key (0x-prefixed hex)
35
+ * @param config - Optional XMTP configuration
36
+ * @throws AzethError if initialization fails
37
+ */
38
+ async initialize(privateKey, config) {
39
+ if (this._ready)
40
+ return;
41
+ // Dynamic import of @xmtp/agent-sdk to keep it optional at load time
42
+ let Agent;
43
+ let ClientClass;
44
+ let createUser;
45
+ let createSigner;
46
+ try {
47
+ const sdk = await import('@xmtp/agent-sdk');
48
+ Agent = sdk.Agent;
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ ClientClass = sdk.Client;
51
+ createUser = sdk.createUser;
52
+ createSigner = sdk.createSigner;
53
+ }
54
+ catch {
55
+ throw new AzethError('XMTP Agent SDK not installed. Run: pnpm add @xmtp/agent-sdk', 'INVALID_INPUT');
56
+ }
57
+ const user = createUser(privateKey);
58
+ const signer = createSigner(user);
59
+ // Resolve encryption key: config -> generate
60
+ let dbEncryptionKey;
61
+ if (config?.dbEncryptionKey) {
62
+ const hex = config.dbEncryptionKey.replace(/^0x/, '');
63
+ if (hex.length !== 64) {
64
+ throw new AzethError('dbEncryptionKey must be exactly 32 bytes (64 hex chars)', 'INVALID_INPUT', { field: 'dbEncryptionKey' });
65
+ }
66
+ dbEncryptionKey = Buffer.from(hex, 'hex');
67
+ }
68
+ else {
69
+ // MEDIUM-7 (Audit): Auto-generating a random encryption key. The XMTP local database
70
+ // will be encrypted with this ephemeral key. On process restart, the key is lost and
71
+ // the database becomes unreadable — all XMTP conversation history and group state will
72
+ // be inaccessible. For persistent messaging, always provide config.dbEncryptionKey.
73
+ console.warn('[XMTPClient] No dbEncryptionKey provided — auto-generating ephemeral key. '
74
+ + 'XMTP message history will be LOST on restart. Set dbEncryptionKey for persistence.');
75
+ dbEncryptionKey = crypto.randomBytes(32);
76
+ }
77
+ const env = config?.env ?? 'production';
78
+ const dbPath = config?.dbPath ?? null;
79
+ try {
80
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
+ this._agent = await Agent.create(signer, {
82
+ env,
83
+ dbPath,
84
+ dbEncryptionKey,
85
+ });
86
+ }
87
+ catch (e) {
88
+ const msg = e instanceof Error ? e.message : String(e);
89
+ // Sanitize XMTP-internal identifiers (InboxIDs, hex hashes) from error messages
90
+ const sanitizedMsg = msg.replace(/[0-9a-fA-F]{32,}/g, '[redacted-id]');
91
+ throw new AzethError(`XMTP client creation failed: ${sanitizedMsg}`, 'NETWORK_ERROR', { cause: 'xmtp', originalError: e instanceof Error ? e.name : undefined });
92
+ }
93
+ // Store Client class + env for static fetchInboxStates calls
94
+ this._ClientClass = ClientClass ?? null;
95
+ this._xmtpEnv = env;
96
+ // Apply config
97
+ this._reachabilityCacheTtlMs = config?.reachabilityCacheTtlMs ?? 300_000;
98
+ this._maxMessageLength = config?.maxMessageLength ?? 10_000;
99
+ this._rateLimiter = new RateLimiter(config?.rateLimitPerMinute ?? 10);
100
+ this._autoReply = config?.autoReply ?? false;
101
+ this._ready = true;
102
+ }
103
+ /** Send a text message to an Ethereum address.
104
+ *
105
+ * Checks reachability, creates or finds a DM conversation, then sends.
106
+ *
107
+ * @param params - Message parameters (to, content, contentType)
108
+ * @returns The conversation ID
109
+ * @throws AzethError if the recipient is unreachable, content exceeds limits, or sending fails
110
+ */
111
+ async sendMessage(params) {
112
+ this._requireReady();
113
+ if (params.content.length > this._maxMessageLength) {
114
+ throw new AzethError(`Message content exceeds maximum length of ${this._maxMessageLength} characters`, 'INVALID_INPUT', { field: 'content', maxLength: this._maxMessageLength });
115
+ }
116
+ const reachable = await this.canReach(params.to);
117
+ if (!reachable) {
118
+ throw new AzethError(`Recipient ${params.to} is not reachable on the XMTP network`, 'RECIPIENT_UNREACHABLE', { address: params.to });
119
+ }
120
+ try {
121
+ const dm = await this._agent.createDmWithAddress(params.to);
122
+ await dm.sendText(params.content);
123
+ return dm.id;
124
+ }
125
+ catch (e) {
126
+ const msg = e instanceof Error ? e.message : String(e);
127
+ // Sanitize XMTP-internal identifiers (InboxIDs, hex hashes) from error messages
128
+ const sanitizedMsg = msg.replace(/[0-9a-fA-F]{32,}/g, '[redacted-id]');
129
+ throw new AzethError(`Failed to send XMTP message: ${sanitizedMsg}`, 'NETWORK_ERROR', { cause: 'xmtp', originalError: e instanceof Error ? e.name : undefined });
130
+ }
131
+ }
132
+ /** Register a handler for incoming messages.
133
+ *
134
+ * Starts the agent's message listener on first handler registration.
135
+ * Returns an unsubscribe function that removes the handler.
136
+ *
137
+ * @param handler - Async function called for each incoming message
138
+ * @returns Unsubscribe function
139
+ */
140
+ onMessage(handler) {
141
+ this._handlers.push(handler);
142
+ if (!this._listening && this._ready) {
143
+ this._startListening();
144
+ }
145
+ return () => {
146
+ this._handlers = this._handlers.filter(h => h !== handler);
147
+ };
148
+ }
149
+ /** Check if an Ethereum address is reachable on the XMTP network.
150
+ *
151
+ * Results are cached with a configurable TTL (default 5 minutes).
152
+ * Returns `false` on errors rather than throwing.
153
+ *
154
+ * @param address - Ethereum address to check
155
+ * @returns Whether the address can receive XMTP messages
156
+ */
157
+ async canReach(address) {
158
+ if (!this._ready || !this._agent)
159
+ return false;
160
+ const key = address.toLowerCase();
161
+ const cached = this._reachabilityCache.get(key);
162
+ if (cached && Date.now() < cached.expiresAt) {
163
+ return cached.reachable;
164
+ }
165
+ try {
166
+ const identifier = { identifier: key, identifierKind: 0 };
167
+ const results = await this._agent.client.canMessage([identifier]);
168
+ const reachable = results.get(key) ?? results.get(address) ?? false;
169
+ this._reachabilityCache.set(key, {
170
+ reachable,
171
+ expiresAt: Date.now() + this._reachabilityCacheTtlMs,
172
+ });
173
+ return reachable;
174
+ }
175
+ catch {
176
+ return false;
177
+ }
178
+ }
179
+ /** List active XMTP conversations.
180
+ *
181
+ * @returns Array of conversation summaries
182
+ */
183
+ async getConversations() {
184
+ if (!this._ready || !this._agent)
185
+ return [];
186
+ try {
187
+ // Include Unknown (0) + Allowed (1) consent states so new incoming DMs are visible.
188
+ // Without this, only Allowed conversations appear and new contacts are invisible.
189
+ const consentStates = [0, 1]; // Unknown, Allowed
190
+ await this._agent.client.conversations.syncAll(consentStates);
191
+ const conversations = await this._agent.client.conversations.list({ consentStates });
192
+ const results = [];
193
+ for (const conv of conversations) {
194
+ const peerAddress = await this._extractPeerAddress(conv);
195
+ results.push({
196
+ id: conv.id,
197
+ peerAddress,
198
+ createdAt: conv.createdAt.getTime(),
199
+ });
200
+ }
201
+ return results;
202
+ }
203
+ catch {
204
+ return [];
205
+ }
206
+ }
207
+ /** Read recent messages from a specific conversation.
208
+ *
209
+ * Syncs conversations first, then fetches messages from the conversation
210
+ * matching the given ID. Returns messages sorted by timestamp (newest first).
211
+ *
212
+ * @param conversationId - The XMTP conversation ID to read from
213
+ * @param limit - Maximum number of messages to return (default 20, max 100)
214
+ * @returns Array of messages with sender, content, and timestamp
215
+ */
216
+ async getMessages(conversationId, limit = 20) {
217
+ if (!this._ready || !this._agent)
218
+ return [];
219
+ const clampedLimit = Math.max(1, Math.min(100, limit));
220
+ try {
221
+ const consentStates = [0, 1]; // Unknown + Allowed
222
+ await this._agent.client.conversations.syncAll(consentStates);
223
+ const conversations = await this._agent.client.conversations.list({ consentStates });
224
+ const conv = conversations.find(c => c.id === conversationId);
225
+ if (!conv)
226
+ return [];
227
+ // Fetch more than requested to compensate for filtered internal messages
228
+ const rawMessages = await conv.messages({ limit: clampedLimit + 10 });
229
+ // Filter out XMTP internal messages (group membership events, etc.)
230
+ // Only include messages with string content (actual user text).
231
+ const textMessages = rawMessages.filter(msg => typeof msg.content === 'string');
232
+ // Batch-resolve sender inbox IDs to Ethereum addresses
233
+ const uniqueSenders = [...new Set(textMessages.map(m => m.senderInboxId).filter(Boolean))];
234
+ const senderMap = new Map();
235
+ if (uniqueSenders.length > 0 && this._ClientClass) {
236
+ try {
237
+ const states = await this._ClientClass.fetchInboxStates(uniqueSenders, this._xmtpEnv);
238
+ for (let i = 0; i < states.length; i++) {
239
+ const state = states[i];
240
+ if (state?.identifiers) {
241
+ for (const id of state.identifiers) {
242
+ if (id.identifierKind === 0 && id.identifier) {
243
+ senderMap.set(uniqueSenders[i], id.identifier);
244
+ break;
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+ catch { /* resolution failed — fall back to inbox IDs */ }
251
+ }
252
+ return textMessages.slice(0, clampedLimit).map(msg => ({
253
+ sender: senderMap.get(msg.senderInboxId) ?? msg.senderInboxId ?? 'unknown',
254
+ content: msg.content,
255
+ contentType: 'text/plain',
256
+ timestamp: Number(msg.sentAtNs / 1000000n), // ns -> ms
257
+ conversationId,
258
+ }));
259
+ }
260
+ catch {
261
+ return [];
262
+ }
263
+ }
264
+ /** Read recent messages from a conversation with a specific peer address.
265
+ *
266
+ * Convenience method that finds the conversation by peer address
267
+ * and reads messages from it.
268
+ *
269
+ * @param peerAddress - The Ethereum address of the conversation peer
270
+ * @param limit - Maximum number of messages to return (default 20, max 100)
271
+ * @returns Array of messages, or empty array if no conversation found
272
+ */
273
+ async getMessagesByPeer(peerAddress, limit = 20) {
274
+ const conversations = await this.getConversations();
275
+ const conv = conversations.find(c => c.peerAddress.toLowerCase() === peerAddress.toLowerCase());
276
+ if (!conv)
277
+ return [];
278
+ return this.getMessages(conv.id, limit);
279
+ }
280
+ /** Whether the client has been successfully initialized and is ready */
281
+ isReady() {
282
+ return this._ready;
283
+ }
284
+ /** Attach a MessageRouter for structured message dispatch.
285
+ *
286
+ * When a router is set and autoReply is enabled (via XMTPConfig or by
287
+ * setting autoReply=true here), incoming messages are automatically
288
+ * routed through the router and responses sent back to the sender.
289
+ *
290
+ * @param router - The MessageRouter instance to use for dispatch
291
+ * @param autoReply - Enable auto-reply (default: uses config value)
292
+ */
293
+ setRouter(router, autoReply) {
294
+ this._messageRouter = router;
295
+ if (autoReply !== undefined) {
296
+ this._autoReply = autoReply;
297
+ }
298
+ }
299
+ /** Tear down the XMTP client.
300
+ *
301
+ * Stops the agent, clears all handlers, caches, and timers.
302
+ */
303
+ async destroy() {
304
+ this._ready = false;
305
+ this._listening = false;
306
+ if (this._messageStreamAbort) {
307
+ this._messageStreamAbort();
308
+ this._messageStreamAbort = null;
309
+ }
310
+ if (this._convStreamAbort) {
311
+ this._convStreamAbort();
312
+ this._convStreamAbort = null;
313
+ }
314
+ if (this._agent) {
315
+ try {
316
+ await this._agent.stop();
317
+ }
318
+ catch {
319
+ // Best-effort cleanup
320
+ }
321
+ this._agent = null;
322
+ }
323
+ this._handlers = [];
324
+ this._reachabilityCache.clear();
325
+ this._messageRouter = null;
326
+ this._autoReply = false;
327
+ if (this._rateLimiter) {
328
+ this._rateLimiter.destroy();
329
+ this._rateLimiter = null;
330
+ }
331
+ }
332
+ // ── Private ──────────────────────────────────────
333
+ _requireReady() {
334
+ if (!this._ready || !this._agent) {
335
+ throw new AzethError('XMTP client not initialized. Call initialize() first.', 'INVALID_INPUT');
336
+ }
337
+ }
338
+ /** Start streaming incoming messages and new conversations */
339
+ _startListening() {
340
+ if (this._listening || !this._agent)
341
+ return;
342
+ this._listening = true;
343
+ const agent = this._agent;
344
+ let abortMessages = false;
345
+ let abortConvs = false;
346
+ this._messageStreamAbort = () => { abortMessages = true; };
347
+ this._convStreamAbort = () => { abortConvs = true; };
348
+ // Stream all messages from existing conversations
349
+ void (async () => {
350
+ try {
351
+ await agent.client.conversations.syncAll([0, 1]); // Unknown + Allowed
352
+ const stream = await agent.client.conversations.streamAllMessages();
353
+ for await (const message of stream) {
354
+ if (abortMessages)
355
+ break;
356
+ // Skip our own messages
357
+ if (message.senderInboxId === agent.client.inboxId)
358
+ continue;
359
+ await this._handleIncoming(message);
360
+ }
361
+ }
362
+ catch (err) {
363
+ if (!abortMessages) {
364
+ const msg = err instanceof Error ? err.message : 'Unknown error';
365
+ console.error('[XMTPClient] Message stream error:', msg);
366
+ this._listening = false;
367
+ }
368
+ }
369
+ })();
370
+ // Stream new conversations to pick up first messages from new contacts
371
+ void (async () => {
372
+ try {
373
+ const stream = await agent.client.conversations.stream();
374
+ for await (const conv of stream) {
375
+ if (abortConvs)
376
+ break;
377
+ await conv.sync();
378
+ }
379
+ }
380
+ catch (err) {
381
+ if (!abortConvs) {
382
+ const msg = err instanceof Error ? err.message : 'Unknown error';
383
+ console.error('[XMTPClient] Conversation stream error:', msg);
384
+ }
385
+ }
386
+ })();
387
+ }
388
+ /** Process a single incoming message from the stream */
389
+ async _handleIncoming(message) {
390
+ // Skip XMTP internal messages (group membership events, etc.)
391
+ if (typeof message.content !== 'string')
392
+ return;
393
+ const content = message.content;
394
+ // Audit #10: Drop oversized messages to prevent memory exhaustion
395
+ const MAX_MESSAGE_SIZE = 65_536; // 64KB
396
+ if (content.length > MAX_MESSAGE_SIZE) {
397
+ return;
398
+ }
399
+ // Rate limit per sender inbox ID
400
+ if (this._rateLimiter && !this._rateLimiter.checkLimit(message.senderInboxId)) {
401
+ return;
402
+ }
403
+ // XMTPMessage.sender is typed as `string` to accommodate XMTP inbox IDs
404
+ // which are not necessarily valid Ethereum addresses.
405
+ const sender = message.senderInboxId ?? 'unknown';
406
+ const xmtpMessage = {
407
+ sender,
408
+ content,
409
+ contentType: 'text/plain',
410
+ timestamp: Number(message.sentAtNs / 1000000n), // ns -> ms
411
+ conversationId: message.conversationId,
412
+ };
413
+ for (const handler of this._handlers) {
414
+ try {
415
+ await handler(xmtpMessage);
416
+ }
417
+ catch {
418
+ // Individual handler errors should not crash the stream
419
+ }
420
+ }
421
+ // Auto-reply via router if enabled
422
+ if (this._messageRouter && this._autoReply) {
423
+ try {
424
+ const response = await this._messageRouter.routeMessage(sender, content);
425
+ // Send response back to the sender's conversation
426
+ const conversations = await this._agent.client.conversations.list({ consentStates: [0, 1] });
427
+ const conv = conversations.find(c => c.id === message.conversationId);
428
+ if (conv) {
429
+ // Use the conversation's send method via DM creation
430
+ // (createDmWithAddress handles finding or creating the conversation)
431
+ const peerAddress = await this._extractPeerAddress(conv);
432
+ const dm = await this._agent.createDmWithAddress(peerAddress);
433
+ await dm.sendText(response);
434
+ }
435
+ }
436
+ catch {
437
+ // Auto-reply errors should not crash the stream
438
+ }
439
+ }
440
+ }
441
+ /** Extract peer address from a conversation object.
442
+ *
443
+ * Uses `peerInboxId` + `client.fetchInboxStates()` to resolve the peer's
444
+ * wallet address. This avoids `conv.members()` which throws an internal
445
+ * error in XMTP SDK v5 due to private field access issues on listed conversations.
446
+ */
447
+ async _extractPeerAddress(conv) {
448
+ try {
449
+ const peerInboxId = conv.peerInboxId;
450
+ if (peerInboxId && this._ClientClass) {
451
+ // Use the static Client.fetchInboxStates — the Agent's client instance
452
+ // doesn't expose this method despite the type declarations claiming so.
453
+ const states = await this._ClientClass.fetchInboxStates([peerInboxId], this._xmtpEnv);
454
+ const state = states?.[0];
455
+ if (state?.identifiers) {
456
+ for (const id of state.identifiers) {
457
+ // identifierKind 0 = Ethereum address
458
+ if (id.identifierKind === 0 && id.identifier) {
459
+ return id.identifier;
460
+ }
461
+ }
462
+ }
463
+ }
464
+ }
465
+ catch {
466
+ // fetchInboxStates can fail on network errors — fall through to sentinel
467
+ }
468
+ // L-13 fix (Audit #8): Return a clearly invalid sentinel rather than the zero address,
469
+ // which could be confused with a real address and cause accidental fund transfers.
470
+ return '0xdeaddeaddeaddeaddeaddeaddeaddeaddeaddead';
471
+ }
472
+ }
473
+ //# sourceMappingURL=xmtp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xmtp.js","sourceRoot":"","sources":["../../src/messaging/xmtp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { type PublicClient, type WalletClient, type Chain, type Transport, type Account } from 'viem';
2
+ import { type AzethContractAddresses, type PaymentAgreement } from '@azeth/common';
3
+ import type { AzethSmartAccountClient } from '../utils/userop.js';
4
+ export interface CreateAgreementParams {
5
+ payee: `0x${string}`;
6
+ token: `0x${string}`;
7
+ amount: bigint;
8
+ interval: number;
9
+ endTime?: bigint;
10
+ maxExecutions?: number;
11
+ totalCap?: bigint;
12
+ }
13
+ export interface AgreementResult {
14
+ agreementId: bigint;
15
+ txHash: `0x${string}`;
16
+ }
17
+ /** Create a recurring payment agreement via ERC-4337 UserOperation.
18
+ *
19
+ * Routes the call through the smart account so msg.sender = smart account address.
20
+ * The SmartAccountClient wraps the PaymentAgreementModule.createAgreement() call
21
+ * inside AzethAccount.execute() via a UserOp submitted to EntryPoint v0.7.
22
+ */
23
+ export declare function createPaymentAgreement(publicClient: PublicClient<Transport, Chain>, smartAccountClient: AzethSmartAccountClient, addresses: AzethContractAddresses, account: `0x${string}`, params: CreateAgreementParams): Promise<AgreementResult>;
24
+ /** Get agreement details */
25
+ export declare function getAgreement(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`, agreementId: bigint): Promise<PaymentAgreement>;
26
+ /** Find an active agreement from a given account to a specific payee.
27
+ * Iterates from newest to oldest (newest more likely active).
28
+ * Scans at most MAX_AGREEMENT_SCAN agreements to prevent O(n) RPC calls.
29
+ *
30
+ * @param publicClient - viem public client for on-chain reads
31
+ * @param addresses - Contract addresses containing paymentAgreementModule
32
+ * @param account - The payer's smart account address
33
+ * @param payee - The payee address to match
34
+ * @param token - Optional token address to filter by
35
+ * @returns The first matching active agreement, or null
36
+ */
37
+ export declare function findAgreementWithPayee(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`, payee: `0x${string}`, token?: `0x${string}`): Promise<PaymentAgreement | null>;
38
+ /** Execute a due payment agreement via ERC-4337 UserOperation.
39
+ *
40
+ * Routes the call through the smart account so msg.sender = smart account address.
41
+ */
42
+ export declare function executeAgreement(publicClient: PublicClient<Transport, Chain>, smartAccountClient: AzethSmartAccountClient, addresses: AzethContractAddresses, account: `0x${string}`, agreementId: bigint): Promise<`0x${string}`>;
43
+ /** Execute a payment agreement as a third-party keeper.
44
+ *
45
+ * The contract's executeAgreement() is permissionless — any msg.sender can trigger it.
46
+ * When the caller is NOT the payer (i.e., it's a keeper or payee), we cannot build a
47
+ * UserOp for the payer's smart account (AA24 signature mismatch). Instead:
48
+ *
49
+ * - If the keeper has their own smart account: route via the keeper's SmartAccountClient
50
+ * (the keeper's smart account calls the module, which executes on the payer's account)
51
+ * - If the keeper has no smart account: call the module directly from the keeper's EOA
52
+ * via walletClient.writeContract()
53
+ */
54
+ export declare function executeAgreementAsKeeper(publicClient: PublicClient<Transport, Chain>, keeperSmartAccountClient: AzethSmartAccountClient | null, walletClient: WalletClient<Transport, Chain, Account>, addresses: AzethContractAddresses, payerAccount: `0x${string}`, agreementId: bigint): Promise<`0x${string}`>;
55
+ /** Cancel an active payment agreement via ERC-4337 UserOperation.
56
+ *
57
+ * Routes the call through the smart account so msg.sender = smart account address.
58
+ * Only the payer (agreement creator) can cancel. Immediate effect, no timelock.
59
+ */
60
+ export declare function cancelAgreement(publicClient: PublicClient<Transport, Chain>, smartAccountClient: AzethSmartAccountClient, addresses: AzethContractAddresses, agreementId: bigint): Promise<`0x${string}`>;
61
+ /** Get the total number of agreements for an account */
62
+ export declare function getAgreementCount(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`): Promise<bigint>;
63
+ /** Check if a payment agreement can be executed right now.
64
+ * Returns [executable, reason] — reason explains why if not executable.
65
+ */
66
+ export declare function canExecutePayment(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`, agreementId: bigint): Promise<{
67
+ executable: boolean;
68
+ reason: string;
69
+ }>;
70
+ /** Check if a payment agreement is executable (ignoring interval timing).
71
+ * Checks: active, not expired, not maxed, not capped, guardian whitelist,
72
+ * guardian limits, and payer balance >= accrued amount. */
73
+ export declare function isAgreementExecutable(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`, agreementId: bigint): Promise<boolean>;
74
+ /** Get comprehensive agreement data in a single RPC call.
75
+ * Combines getAgreement + isAgreementExecutable + isAgreementDue +
76
+ * getNextExecutionTime + getAgreementCount. */
77
+ export declare function getAgreementData(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`, agreementId: bigint): Promise<{
78
+ agreement: PaymentAgreement;
79
+ executable: boolean;
80
+ reason: string;
81
+ isDue: boolean;
82
+ nextExecutionTime: bigint;
83
+ count: bigint;
84
+ }>;
85
+ /** Get the next execution timestamp for a payment agreement */
86
+ export declare function getNextExecutionTime(publicClient: PublicClient<Transport, Chain>, addresses: AzethContractAddresses, account: `0x${string}`, agreementId: bigint): Promise<bigint>;
87
+ //# sourceMappingURL=agreements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agreements.d.ts","sourceRoot":"","sources":["../../src/payments/agreements.ts"],"names":[],"mappings":"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"}