@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.
- package/README.md +41 -7
- package/dist/index.cjs +415 -3085
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -828
- package/dist/index.d.ts +12 -828
- package/dist/index.js +416 -3056
- package/dist/index.js.map +1 -1
- package/package.json +18 -5
- package/src/client.ts +23 -135
- package/src/index.ts +28 -81
- package/src/index.ts.old +145 -0
- package/src/lib/jwt.ts +45 -13
- package/src/lib/{message-listener.test.ts → message-listener.test.ts.old} +1 -1
- package/src/lib/subjects.ts +6 -5
- package/src/plugin.filters.test.ts +158 -0
- package/src/plugin.ts +456 -23
- package/src/resolver/address-resolver.ts +217 -211
- package/src/resolver/basename-resolver.ts +6 -5
- package/src/resolver/ens-resolver.ts +15 -14
- package/src/resolver/resolver.ts +3 -2
- package/src/resolver/xmtp-resolver.ts +10 -9
- package/src/{service-client.ts → service-client.ts.old} +26 -3
- package/src/types.ts +9 -157
- package/src/types.ts.old +157 -0
- package/.cache/tsbuildinfo.json +0 -1
- package/.turbo/turbo-build.log +0 -45
- package/.turbo/turbo-lint$colon$fix.log +0 -6
- package/.turbo/turbo-typecheck.log +0 -5
- package/biome.jsonc +0 -4
- package/scripts/generate-keys.ts +0 -25
- package/scripts/refresh-identity.ts +0 -119
- package/scripts/register-wallet.ts +0 -95
- package/scripts/revoke-all-installations.ts +0 -91
- package/scripts/revoke-installations.ts +0 -94
- package/src/endpoints.ts +0 -306
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -14
- /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
package/tsup.config.ts
DELETED
|
File without changes
|