@hybrd/xmtp 1.3.2 → 1.4.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 (38) hide show
  1. package/README.md +41 -7
  2. package/dist/index.cjs +415 -3085
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +12 -828
  5. package/dist/index.d.ts +12 -828
  6. package/dist/index.js +416 -3056
  7. package/dist/index.js.map +1 -1
  8. package/package.json +18 -5
  9. package/src/client.ts +23 -135
  10. package/src/index.ts +28 -81
  11. package/src/index.ts.old +145 -0
  12. package/src/lib/jwt.ts +45 -13
  13. package/src/lib/{message-listener.test.ts → message-listener.test.ts.old} +1 -1
  14. package/src/lib/subjects.ts +6 -5
  15. package/src/plugin.filters.test.ts +158 -0
  16. package/src/plugin.ts +456 -23
  17. package/src/resolver/address-resolver.ts +217 -211
  18. package/src/resolver/basename-resolver.ts +6 -5
  19. package/src/resolver/ens-resolver.ts +15 -14
  20. package/src/resolver/resolver.ts +3 -2
  21. package/src/resolver/xmtp-resolver.ts +10 -9
  22. package/src/{service-client.ts → service-client.ts.old} +26 -3
  23. package/src/types.ts +9 -157
  24. package/src/types.ts.old +157 -0
  25. package/.cache/tsbuildinfo.json +0 -1
  26. package/.turbo/turbo-build.log +0 -45
  27. package/.turbo/turbo-lint$colon$fix.log +0 -6
  28. package/.turbo/turbo-typecheck.log +0 -5
  29. package/biome.jsonc +0 -4
  30. package/scripts/generate-keys.ts +0 -25
  31. package/scripts/refresh-identity.ts +0 -119
  32. package/scripts/register-wallet.ts +0 -95
  33. package/scripts/revoke-all-installations.ts +0 -91
  34. package/scripts/revoke-installations.ts +0 -94
  35. package/src/endpoints.ts +0 -306
  36. package/tsconfig.json +0 -9
  37. package/tsup.config.ts +0 -14
  38. /package/src/lib/{message-listener.ts → message-listener.ts.old} +0 -0
package/src/endpoints.ts DELETED
@@ -1,306 +0,0 @@
1
- import { ContentTypeReaction } from "@xmtp/content-type-reaction"
2
- import { ContentTypeReply, Reply } from "@xmtp/content-type-reply"
3
- import { ContentTypeText } from "@xmtp/content-type-text"
4
- import { ContentTypeWalletSendCalls, WalletSendCallsParams } from "@xmtp/content-type-wallet-send-calls"
5
- import { Hono } from "hono"
6
- import { getValidatedPayload, validateXMTPToolsToken } from "./lib/jwt"
7
- import type { HonoVariables, SendMessageParams, SendReactionParams, SendReplyParams, SendTransactionParams } from "./types"
8
-
9
- const app = new Hono<{ Variables: HonoVariables }>()
10
-
11
- app.get("/messages/:messageId", async (c) => {
12
- const xmtpClient = c.get("xmtpClient")
13
-
14
- if (!xmtpClient) {
15
- return c.json({ error: "XMTP client not initialized" }, 500)
16
- }
17
-
18
- const token = c.req.query("token")
19
-
20
- if (!token) {
21
- return c.json({ error: "Token required" }, 401)
22
- }
23
-
24
- const payload = validateXMTPToolsToken(token)
25
- if (!payload) {
26
- return c.json({ error: "Invalid or expired token" }, 401)
27
- }
28
-
29
- const messageId = c.req.param("messageId")
30
-
31
- try {
32
- const message = await xmtpClient.conversations.getMessageById(messageId)
33
- if (!message) {
34
- return c.json({ error: "Message not found" }, 404)
35
- }
36
-
37
- console.log(`✅ Retrieved message ${messageId}`)
38
-
39
- const transformedMessage = {
40
- id: message.id,
41
- senderInboxId: message.senderInboxId,
42
- sentAt: message.sentAt.toISOString(),
43
- content:
44
- typeof message.content === "object"
45
- ? JSON.stringify(message.content)
46
- : message.content,
47
- contentType: message.contentType?.typeId || "text",
48
- conversationId: message.conversationId,
49
- parameters: (message.contentType as any)?.parameters || {}
50
- }
51
-
52
- return c.json(transformedMessage)
53
- } catch (error) {
54
- console.error("❌ Error fetching message:", error)
55
- return c.json({ error: "Failed to fetch message" }, 500)
56
- }
57
- })
58
-
59
- // XMTP Tools endpoints
60
- app.post("/send", async (c) => {
61
- const xmtpClient = c.get("xmtpClient")
62
-
63
- if (!xmtpClient) {
64
- return c.json({ error: "XMTP client not initialized" }, 500)
65
- }
66
-
67
- const payload = getValidatedPayload(c)
68
- if (!payload) {
69
- return c.json({ error: "Invalid or expired token" }, 401)
70
- }
71
-
72
- // Get request body data
73
- const body = await c.req.json<SendMessageParams>()
74
-
75
- // Content can come from JWT payload or request body
76
- const content = body.content || payload.content
77
- if (!content) {
78
- return c.json({ error: "Content required for send action" }, 400)
79
- }
80
-
81
- const conversationId = payload.conversationId
82
-
83
- // Conversation ID can come from JWT payload or request body (for API key auth)
84
- // const conversationId = payload.conversationId || body.conversationId
85
- if (!conversationId) {
86
- return c.json({ error: "Conversation ID required" }, 400)
87
- }
88
-
89
- try {
90
- const conversation =
91
- await xmtpClient.conversations.getConversationById(conversationId)
92
- if (!conversation) {
93
- return c.json({ error: "Conversation not found" }, 404)
94
- }
95
-
96
- await conversation.send(content)
97
- console.log(`➡ Sent message to conversation ${conversationId}`)
98
-
99
- return c.json({
100
- success: true,
101
- action: "send",
102
- conversationId: payload.conversationId
103
- })
104
- } catch (error) {
105
- console.error("❌ Error sending message:", error)
106
- return c.json({ error: "Failed to send message" }, 500)
107
- }
108
- })
109
-
110
- app.post("/reply", async (c) => {
111
- const xmtpClient = c.get("xmtpClient")
112
-
113
- if (!xmtpClient) {
114
- return c.json({ error: "XMTP client not initialized" }, 500)
115
- }
116
-
117
- const payload = getValidatedPayload(c)
118
- if (!payload) {
119
- return c.json({ error: "Invalid or expired token" }, 401)
120
- }
121
-
122
- // Get request body data
123
- const body = await c.req.json<SendReplyParams>()
124
-
125
- // Content can come from JWT payload or request body
126
- const content = body.content || payload.content
127
- if (!content) {
128
- return c.json({ error: "Content required for reply action" }, 400)
129
- }
130
-
131
- // Reference message ID can come from JWT payload or request body
132
- const messageId = body.messageId
133
-
134
- if (!messageId) {
135
- return c.json(
136
- { error: "Reference message ID required for reply action" },
137
- 400
138
- )
139
- }
140
-
141
- try {
142
- const conversation = await xmtpClient.conversations.getConversationById(
143
- payload.conversationId
144
- )
145
- if (!conversation) {
146
- return c.json({ error: "Conversation not found" }, 404)
147
- }
148
-
149
- // Create proper XMTP reply structure
150
- const reply: Reply = {
151
- reference: messageId,
152
- contentType: ContentTypeText,
153
- content: content
154
- }
155
-
156
- // Send as a proper threaded reply
157
- await conversation.send(reply, ContentTypeReply)
158
- console.log(
159
- `➡ Sent reply "${content}" to conversation ${payload.conversationId}`
160
- )
161
-
162
- return c.json({
163
- success: true,
164
- action: "reply",
165
- conversationId: payload.conversationId
166
- })
167
- } catch (error) {
168
- console.error("❌ Error sending reply:", error)
169
- return c.json({ error: "Failed to send reply" }, 500)
170
- }
171
- })
172
-
173
- app.post("/react", async (c) => {
174
- const xmtpClient = c.get("xmtpClient")
175
-
176
- if (!xmtpClient) {
177
- return c.json({ error: "XMTP client not initialized" }, 500)
178
- }
179
-
180
- const payload = getValidatedPayload(c)
181
- if (!payload) {
182
- return c.json({ error: "Invalid or expired token" }, 401)
183
- }
184
-
185
- // Get request body data
186
- const body = await c.req.json<SendReactionParams>()
187
-
188
- if (!body.emoji) {
189
- return c.json({ error: "Emoji required for react action" }, 400)
190
- }
191
-
192
- try {
193
- const conversation = await xmtpClient.conversations.getConversationById(
194
- payload.conversationId
195
- )
196
- if (!conversation) {
197
- return c.json({ error: "Conversation not found" }, 404)
198
- }
199
-
200
- const reaction = {
201
- schema: "unicode",
202
- reference: body.messageId,
203
- action: body.action,
204
- contentType: ContentTypeReaction,
205
- content: body.emoji
206
- }
207
-
208
- // For now, send the reaction content as a simple text message
209
- // This will send "eyes" as text content to indicate message was seen
210
- await conversation.send(reaction, ContentTypeReaction)
211
-
212
- console.log(
213
- `➡ Sent reaction ${body.emoji} to message ${body.messageId} in conversation ${payload.conversationId}`
214
- )
215
-
216
- return c.json({
217
- success: true,
218
- action: "react",
219
- conversationId: payload.conversationId
220
- })
221
- } catch (error) {
222
- console.error("❌ Error sending reaction:", error)
223
- return c.json({ error: "Failed to send reaction" }, 500)
224
- }
225
- })
226
-
227
- app.post("/transaction", async (c) => {
228
- const xmtpClient = c.get("xmtpClient")
229
-
230
- if (!xmtpClient) {
231
- return c.json({ error: "XMTP client not initialized" }, 500)
232
- }
233
-
234
- const payload = getValidatedPayload(c)
235
- if (!payload) {
236
- return c.json({ error: "Invalid or expired token" }, 401)
237
- }
238
-
239
- // Get request body data for backward compatibility
240
- let body: any = {}
241
- try {
242
- body = await c.req.json<SendTransactionParams>()
243
- } catch (error) {
244
- body = {}
245
- }
246
-
247
- // Transaction data can come from JWT payload (preferred) or request body (fallback)
248
- const fromAddress = payload.fromAddress || body.fromAddress
249
- const chainId = payload.chainId || body.chainId
250
- const calls = payload.calls || body.calls
251
-
252
- if (!calls || !fromAddress || !chainId) {
253
- return c.json(
254
- { error: "Transaction data required for transaction action" },
255
- 400
256
- )
257
- }
258
-
259
- // CRITICAL: Detect data truncation that can cause transaction failures
260
- calls.forEach((call: any, index: number) => {
261
- if (call.data && typeof call.data === "string") {
262
- const actualStart = call.data.substring(0, 10)
263
-
264
- if (actualStart === "0x010f2e2e") {
265
- console.error("🚨 CRITICAL: Transaction data truncation detected!")
266
- console.error(" Function selector corrupted - transaction will fail")
267
- console.error(
268
- " This indicates a bug in wallet software or XMTP transmission"
269
- )
270
- }
271
- }
272
- })
273
-
274
- try {
275
- const conversation = await xmtpClient.conversations.getConversationById(
276
- payload.conversationId
277
- )
278
- if (!conversation) {
279
- return c.json({ error: "Conversation not found" }, 404)
280
- }
281
-
282
- const params: WalletSendCallsParams = {
283
- version: "1",
284
- chainId,
285
- from: fromAddress,
286
- calls
287
- }
288
-
289
- await conversation.send(params, ContentTypeWalletSendCalls)
290
-
291
- console.log(
292
- `✅ Sent transaction request to conversation ${payload.conversationId}`
293
- )
294
-
295
- return c.json({
296
- success: true,
297
- action: "transaction",
298
- conversationId: payload.conversationId
299
- })
300
- } catch (error) {
301
- console.error("❌ Error sending transaction:", error)
302
- return c.json({ error: "Failed to send transaction" }, 500)
303
- }
304
- })
305
-
306
- export default app
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "@config/tsconfig/external-package.json",
3
- "compilerOptions": {
4
- "emitDeclarationOnly": false,
5
- "outDir": "dist"
6
- },
7
- "include": ["src/**/*.ts", "src/**/*.tsx"],
8
- "exclude": ["node_modules"]
9
- }
package/tsup.config.ts DELETED
@@ -1,14 +0,0 @@
1
- import { defineConfig } from "tsup"
2
-
3
- export default defineConfig({
4
- entry: {
5
- index: "src/index.ts"
6
- },
7
- format: ["cjs", "esm"],
8
- dts: true,
9
- splitting: false,
10
- sourcemap: true,
11
- clean: true,
12
- outDir: "dist",
13
- target: "es2020"
14
- })