@hybrd/xmtp 1.2.7 → 1.3.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/.cache/tsbuildinfo.json +1 -1
- package/.turbo/turbo-build.log +12 -12
- package/.turbo/turbo-lint$colon$fix.log +2 -2
- package/.turbo/turbo-typecheck.log +5 -0
- package/dist/index.cjs +348 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +345 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/endpoints.ts +306 -0
- package/src/index.ts +15 -3
- package/src/lib/jwt.ts +220 -0
- package/src/plugin.ts +39 -0
package/dist/index.d.cts
CHANGED
|
@@ -13,6 +13,7 @@ import { WalletSendCallsParams } from '@xmtp/content-type-wallet-send-calls';
|
|
|
13
13
|
export { ContentTypeWalletSendCalls, WalletSendCallsParams } from '@xmtp/content-type-wallet-send-calls';
|
|
14
14
|
import { PublicClient, Address } from 'viem';
|
|
15
15
|
import { EventEmitter } from 'node:events';
|
|
16
|
+
import { Hono } from 'hono';
|
|
16
17
|
export { ContentTypeText, TextParameters } from '@xmtp/content-type-text';
|
|
17
18
|
|
|
18
19
|
declare const BasenameTextRecordKeys: {
|
|
@@ -857,4 +858,66 @@ declare function createAuthenticatedXmtpClient(callbackUrl?: string, callbackTok
|
|
|
857
858
|
*/
|
|
858
859
|
declare function getXMTPToolsUrl(baseUrl: string, action: string, token: string): string;
|
|
859
860
|
|
|
860
|
-
|
|
861
|
+
interface Plugin<TContext = unknown> {
|
|
862
|
+
name: string;
|
|
863
|
+
description?: string;
|
|
864
|
+
apply: (app: Hono<{
|
|
865
|
+
Variables: HonoVariables;
|
|
866
|
+
}>, context?: TContext) => void | Promise<void>;
|
|
867
|
+
}
|
|
868
|
+
interface XMTPPluginContext {
|
|
869
|
+
agent: unknown;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* XMTP Plugin that provides XMTP functionality to the agent
|
|
873
|
+
*
|
|
874
|
+
* @description
|
|
875
|
+
* This plugin integrates XMTP messaging capabilities into the agent's
|
|
876
|
+
* HTTP server. It mounts the XMTP endpoints for handling XMTP tools requests.
|
|
877
|
+
*/
|
|
878
|
+
declare function XMTPPlugin({ filter }?: {
|
|
879
|
+
filter?: MessageListenerConfig["filter"];
|
|
880
|
+
}): Plugin<XMTPPluginContext>;
|
|
881
|
+
|
|
882
|
+
interface XMTPToolsPayload {
|
|
883
|
+
action: "send" | "reply" | "react" | "transaction" | "blockchain-event";
|
|
884
|
+
conversationId: string;
|
|
885
|
+
content?: string;
|
|
886
|
+
referenceMessageId?: string;
|
|
887
|
+
emoji?: string;
|
|
888
|
+
actionType?: "added" | "removed";
|
|
889
|
+
fromAddress?: string;
|
|
890
|
+
chainId?: string;
|
|
891
|
+
calls?: Array<{
|
|
892
|
+
to: string;
|
|
893
|
+
data: string;
|
|
894
|
+
metadata?: {
|
|
895
|
+
description: string;
|
|
896
|
+
transactionType: string;
|
|
897
|
+
};
|
|
898
|
+
}>;
|
|
899
|
+
issued: number;
|
|
900
|
+
expires: number;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Generates a signed JWT token for XMTP tools authentication
|
|
904
|
+
*
|
|
905
|
+
* @param {Omit<XMTPToolsPayload, "issued" | "expires">} payload - Token payload without timestamp fields
|
|
906
|
+
* @returns {string} Signed JWT token
|
|
907
|
+
*
|
|
908
|
+
* @description
|
|
909
|
+
* Creates a JWT token with automatic timestamp fields:
|
|
910
|
+
* - issued: Current timestamp
|
|
911
|
+
* - expires: Current timestamp + JWT_EXPIRY
|
|
912
|
+
*
|
|
913
|
+
* @example
|
|
914
|
+
* ```typescript
|
|
915
|
+
* const token = generateXMTPToolsToken({
|
|
916
|
+
* action: "send",
|
|
917
|
+
* conversationId: "0x123..."
|
|
918
|
+
* });
|
|
919
|
+
* ```
|
|
920
|
+
*/
|
|
921
|
+
declare function generateXMTPToolsToken(payload: Omit<XMTPToolsPayload, "issued" | "expires">): string;
|
|
922
|
+
|
|
923
|
+
export { type BaseName, BasenameResolver, type BasenameTextRecordKey, BasenameTextRecordKeys, DEFAULT_AMOUNT, DEFAULT_OPTIONS, ENSResolver, type GetMessageParams, type GetRootMessageParams, type HonoVariables, MAX_USDC_AMOUNT, type MessageEvent, MessageListener, type MessageListenerConfig, type MessageListenerEvents, type Plugin, Resolver, type SendMessageParams, type SendMessageResponse, type SendReactionParams, type SendReactionResponse, type SendReplyParams, type SendReplyResponse, type SendTransactionParams, type SendTransactionResponse, type TransactionCall, type TransactionRequest, type XMTPConnectionConfig, type XMTPConnectionHealth, XMTPConnectionManager, XMTPPlugin, type XMTPPluginContext, type XMTPToolsPayload, type XmtpAuthConfig, type XmtpClient, type XmtpConversation, type XmtpMessage, XmtpResolver, type XmtpRootMessageResponse, type XmtpSender, XmtpServiceClient, type XmtpServiceClientConfig, type XmtpServiceMessage, type XmtpServiceResponse, type XmtpSubjects, backupDbToPersistentStorage, convertChainIdToCoinType, convertReverseNodeToBytes, createAuthenticatedXmtpClient, createMessageListener, createSigner, createUser, createXMTPClient, createXMTPConnectionManager, createXmtpServiceClient, diagnoseXMTPIdentityIssue, extractMentionedNames, extractSubjects, generateEncryptionKeyHex, generateXMTPToolsToken, getDbPath, getEncryptionKeyFromHex, getXMTPToolsUrl, getXmtpAuthConfig, logAgentDetails, resolveSubjects, resolveUserAddress, startMessageListener, startPeriodicBackup, validateEnvironment };
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { WalletSendCallsParams } from '@xmtp/content-type-wallet-send-calls';
|
|
|
13
13
|
export { ContentTypeWalletSendCalls, WalletSendCallsParams } from '@xmtp/content-type-wallet-send-calls';
|
|
14
14
|
import { PublicClient, Address } from 'viem';
|
|
15
15
|
import { EventEmitter } from 'node:events';
|
|
16
|
+
import { Hono } from 'hono';
|
|
16
17
|
export { ContentTypeText, TextParameters } from '@xmtp/content-type-text';
|
|
17
18
|
|
|
18
19
|
declare const BasenameTextRecordKeys: {
|
|
@@ -857,4 +858,66 @@ declare function createAuthenticatedXmtpClient(callbackUrl?: string, callbackTok
|
|
|
857
858
|
*/
|
|
858
859
|
declare function getXMTPToolsUrl(baseUrl: string, action: string, token: string): string;
|
|
859
860
|
|
|
860
|
-
|
|
861
|
+
interface Plugin<TContext = unknown> {
|
|
862
|
+
name: string;
|
|
863
|
+
description?: string;
|
|
864
|
+
apply: (app: Hono<{
|
|
865
|
+
Variables: HonoVariables;
|
|
866
|
+
}>, context?: TContext) => void | Promise<void>;
|
|
867
|
+
}
|
|
868
|
+
interface XMTPPluginContext {
|
|
869
|
+
agent: unknown;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* XMTP Plugin that provides XMTP functionality to the agent
|
|
873
|
+
*
|
|
874
|
+
* @description
|
|
875
|
+
* This plugin integrates XMTP messaging capabilities into the agent's
|
|
876
|
+
* HTTP server. It mounts the XMTP endpoints for handling XMTP tools requests.
|
|
877
|
+
*/
|
|
878
|
+
declare function XMTPPlugin({ filter }?: {
|
|
879
|
+
filter?: MessageListenerConfig["filter"];
|
|
880
|
+
}): Plugin<XMTPPluginContext>;
|
|
881
|
+
|
|
882
|
+
interface XMTPToolsPayload {
|
|
883
|
+
action: "send" | "reply" | "react" | "transaction" | "blockchain-event";
|
|
884
|
+
conversationId: string;
|
|
885
|
+
content?: string;
|
|
886
|
+
referenceMessageId?: string;
|
|
887
|
+
emoji?: string;
|
|
888
|
+
actionType?: "added" | "removed";
|
|
889
|
+
fromAddress?: string;
|
|
890
|
+
chainId?: string;
|
|
891
|
+
calls?: Array<{
|
|
892
|
+
to: string;
|
|
893
|
+
data: string;
|
|
894
|
+
metadata?: {
|
|
895
|
+
description: string;
|
|
896
|
+
transactionType: string;
|
|
897
|
+
};
|
|
898
|
+
}>;
|
|
899
|
+
issued: number;
|
|
900
|
+
expires: number;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Generates a signed JWT token for XMTP tools authentication
|
|
904
|
+
*
|
|
905
|
+
* @param {Omit<XMTPToolsPayload, "issued" | "expires">} payload - Token payload without timestamp fields
|
|
906
|
+
* @returns {string} Signed JWT token
|
|
907
|
+
*
|
|
908
|
+
* @description
|
|
909
|
+
* Creates a JWT token with automatic timestamp fields:
|
|
910
|
+
* - issued: Current timestamp
|
|
911
|
+
* - expires: Current timestamp + JWT_EXPIRY
|
|
912
|
+
*
|
|
913
|
+
* @example
|
|
914
|
+
* ```typescript
|
|
915
|
+
* const token = generateXMTPToolsToken({
|
|
916
|
+
* action: "send",
|
|
917
|
+
* conversationId: "0x123..."
|
|
918
|
+
* });
|
|
919
|
+
* ```
|
|
920
|
+
*/
|
|
921
|
+
declare function generateXMTPToolsToken(payload: Omit<XMTPToolsPayload, "issued" | "expires">): string;
|
|
922
|
+
|
|
923
|
+
export { type BaseName, BasenameResolver, type BasenameTextRecordKey, BasenameTextRecordKeys, DEFAULT_AMOUNT, DEFAULT_OPTIONS, ENSResolver, type GetMessageParams, type GetRootMessageParams, type HonoVariables, MAX_USDC_AMOUNT, type MessageEvent, MessageListener, type MessageListenerConfig, type MessageListenerEvents, type Plugin, Resolver, type SendMessageParams, type SendMessageResponse, type SendReactionParams, type SendReactionResponse, type SendReplyParams, type SendReplyResponse, type SendTransactionParams, type SendTransactionResponse, type TransactionCall, type TransactionRequest, type XMTPConnectionConfig, type XMTPConnectionHealth, XMTPConnectionManager, XMTPPlugin, type XMTPPluginContext, type XMTPToolsPayload, type XmtpAuthConfig, type XmtpClient, type XmtpConversation, type XmtpMessage, XmtpResolver, type XmtpRootMessageResponse, type XmtpSender, XmtpServiceClient, type XmtpServiceClientConfig, type XmtpServiceMessage, type XmtpServiceResponse, type XmtpSubjects, backupDbToPersistentStorage, convertChainIdToCoinType, convertReverseNodeToBytes, createAuthenticatedXmtpClient, createMessageListener, createSigner, createUser, createXMTPClient, createXMTPConnectionManager, createXmtpServiceClient, diagnoseXMTPIdentityIssue, extractMentionedNames, extractSubjects, generateEncryptionKeyHex, generateXMTPToolsToken, getDbPath, getEncryptionKeyFromHex, getXMTPToolsUrl, getXmtpAuthConfig, logAgentDetails, resolveSubjects, resolveUserAddress, startMessageListener, startPeriodicBackup, validateEnvironment };
|
package/dist/index.js
CHANGED
|
@@ -3250,6 +3250,341 @@ function getXMTPToolsUrl(baseUrl, action, token) {
|
|
|
3250
3250
|
return `${baseUrl}/xmtp-tools/${action}?token=${token}`;
|
|
3251
3251
|
}
|
|
3252
3252
|
|
|
3253
|
+
// src/endpoints.ts
|
|
3254
|
+
import { ContentTypeReaction } from "@xmtp/content-type-reaction";
|
|
3255
|
+
import { ContentTypeReply } from "@xmtp/content-type-reply";
|
|
3256
|
+
import { ContentTypeText } from "@xmtp/content-type-text";
|
|
3257
|
+
import { ContentTypeWalletSendCalls } from "@xmtp/content-type-wallet-send-calls";
|
|
3258
|
+
import { Hono } from "hono";
|
|
3259
|
+
|
|
3260
|
+
// src/lib/jwt.ts
|
|
3261
|
+
import jwt from "jsonwebtoken";
|
|
3262
|
+
function getValidatedPayload(c) {
|
|
3263
|
+
const authHeader = c.req.header("Authorization");
|
|
3264
|
+
if (authHeader?.startsWith("Bearer ")) {
|
|
3265
|
+
const token2 = authHeader.substring(7);
|
|
3266
|
+
return validateXMTPToolsToken(token2);
|
|
3267
|
+
}
|
|
3268
|
+
const token = c.req.query("token");
|
|
3269
|
+
if (!token) {
|
|
3270
|
+
return null;
|
|
3271
|
+
}
|
|
3272
|
+
return validateXMTPToolsToken(token);
|
|
3273
|
+
}
|
|
3274
|
+
var JWT_SECRET = (() => {
|
|
3275
|
+
const secret = process.env.XMTP_JWT_SECRET;
|
|
3276
|
+
const nodeEnv = process.env.NODE_ENV || "development";
|
|
3277
|
+
if (nodeEnv === "production" && !secret) {
|
|
3278
|
+
throw new Error(
|
|
3279
|
+
"XMTP_JWT_SECRET environment variable is required in production. Generate a secure random secret for JWT token signing."
|
|
3280
|
+
);
|
|
3281
|
+
}
|
|
3282
|
+
if (!secret) {
|
|
3283
|
+
console.warn(
|
|
3284
|
+
"\u26A0\uFE0F [SECURITY] Using fallback JWT secret for development. Set XMTP_JWT_SECRET environment variable for production."
|
|
3285
|
+
);
|
|
3286
|
+
return "fallback-secret-for-dev-only";
|
|
3287
|
+
}
|
|
3288
|
+
return secret;
|
|
3289
|
+
})();
|
|
3290
|
+
var API_KEY = (() => {
|
|
3291
|
+
const apiKey = process.env.XMTP_API_KEY;
|
|
3292
|
+
const nodeEnv = process.env.NODE_ENV || "development";
|
|
3293
|
+
if (nodeEnv === "production" && !apiKey) {
|
|
3294
|
+
throw new Error(
|
|
3295
|
+
"XMTP_API_KEY environment variable is required in production. Generate a secure random API key for authentication."
|
|
3296
|
+
);
|
|
3297
|
+
}
|
|
3298
|
+
if (!apiKey) {
|
|
3299
|
+
console.warn(
|
|
3300
|
+
"\u26A0\uFE0F [SECURITY] Using fallback API key for development. Set XMTP_API_KEY environment variable for production."
|
|
3301
|
+
);
|
|
3302
|
+
return "fallback-api-key-for-dev-only";
|
|
3303
|
+
}
|
|
3304
|
+
return apiKey;
|
|
3305
|
+
})();
|
|
3306
|
+
var JWT_EXPIRY = 5 * 60;
|
|
3307
|
+
function generateXMTPToolsToken(payload) {
|
|
3308
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3309
|
+
const fullPayload = {
|
|
3310
|
+
...payload,
|
|
3311
|
+
issued: now,
|
|
3312
|
+
expires: now + JWT_EXPIRY
|
|
3313
|
+
};
|
|
3314
|
+
return jwt.sign(fullPayload, JWT_SECRET, {
|
|
3315
|
+
expiresIn: JWT_EXPIRY
|
|
3316
|
+
});
|
|
3317
|
+
}
|
|
3318
|
+
function validateXMTPToolsToken(token) {
|
|
3319
|
+
if (token === API_KEY) {
|
|
3320
|
+
console.log("\u{1F511} [Auth] Using API key authentication");
|
|
3321
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3322
|
+
return {
|
|
3323
|
+
action: "send",
|
|
3324
|
+
// Default action
|
|
3325
|
+
conversationId: "",
|
|
3326
|
+
// Will be filled by endpoint
|
|
3327
|
+
issued: now,
|
|
3328
|
+
expires: now + 3600
|
|
3329
|
+
// API keys are valid for 1 hour
|
|
3330
|
+
};
|
|
3331
|
+
}
|
|
3332
|
+
try {
|
|
3333
|
+
const decoded = jwt.verify(token, JWT_SECRET);
|
|
3334
|
+
console.log("\u{1F511} [Auth] Using JWT token authentication");
|
|
3335
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3336
|
+
if (decoded.expires < now) {
|
|
3337
|
+
console.warn("\u{1F512} XMTP tools token has expired");
|
|
3338
|
+
return null;
|
|
3339
|
+
}
|
|
3340
|
+
return decoded;
|
|
3341
|
+
} catch (error) {
|
|
3342
|
+
console.error(
|
|
3343
|
+
"\u{1F512} Invalid XMTP tools token and not matching API key:",
|
|
3344
|
+
error
|
|
3345
|
+
);
|
|
3346
|
+
return null;
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
|
|
3350
|
+
// src/endpoints.ts
|
|
3351
|
+
var app = new Hono();
|
|
3352
|
+
app.get("/messages/:messageId", async (c) => {
|
|
3353
|
+
const xmtpClient = c.get("xmtpClient");
|
|
3354
|
+
if (!xmtpClient) {
|
|
3355
|
+
return c.json({ error: "XMTP client not initialized" }, 500);
|
|
3356
|
+
}
|
|
3357
|
+
const token = c.req.query("token");
|
|
3358
|
+
if (!token) {
|
|
3359
|
+
return c.json({ error: "Token required" }, 401);
|
|
3360
|
+
}
|
|
3361
|
+
const payload = validateXMTPToolsToken(token);
|
|
3362
|
+
if (!payload) {
|
|
3363
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
3364
|
+
}
|
|
3365
|
+
const messageId = c.req.param("messageId");
|
|
3366
|
+
try {
|
|
3367
|
+
const message = await xmtpClient.conversations.getMessageById(messageId);
|
|
3368
|
+
if (!message) {
|
|
3369
|
+
return c.json({ error: "Message not found" }, 404);
|
|
3370
|
+
}
|
|
3371
|
+
console.log(`\u2705 Retrieved message ${messageId}`);
|
|
3372
|
+
const transformedMessage = {
|
|
3373
|
+
id: message.id,
|
|
3374
|
+
senderInboxId: message.senderInboxId,
|
|
3375
|
+
sentAt: message.sentAt.toISOString(),
|
|
3376
|
+
content: typeof message.content === "object" ? JSON.stringify(message.content) : message.content,
|
|
3377
|
+
contentType: message.contentType?.typeId || "text",
|
|
3378
|
+
conversationId: message.conversationId,
|
|
3379
|
+
parameters: message.contentType?.parameters || {}
|
|
3380
|
+
};
|
|
3381
|
+
return c.json(transformedMessage);
|
|
3382
|
+
} catch (error) {
|
|
3383
|
+
console.error("\u274C Error fetching message:", error);
|
|
3384
|
+
return c.json({ error: "Failed to fetch message" }, 500);
|
|
3385
|
+
}
|
|
3386
|
+
});
|
|
3387
|
+
app.post("/send", async (c) => {
|
|
3388
|
+
const xmtpClient = c.get("xmtpClient");
|
|
3389
|
+
if (!xmtpClient) {
|
|
3390
|
+
return c.json({ error: "XMTP client not initialized" }, 500);
|
|
3391
|
+
}
|
|
3392
|
+
const payload = getValidatedPayload(c);
|
|
3393
|
+
if (!payload) {
|
|
3394
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
3395
|
+
}
|
|
3396
|
+
const body = await c.req.json();
|
|
3397
|
+
const content = body.content || payload.content;
|
|
3398
|
+
if (!content) {
|
|
3399
|
+
return c.json({ error: "Content required for send action" }, 400);
|
|
3400
|
+
}
|
|
3401
|
+
const conversationId = payload.conversationId;
|
|
3402
|
+
if (!conversationId) {
|
|
3403
|
+
return c.json({ error: "Conversation ID required" }, 400);
|
|
3404
|
+
}
|
|
3405
|
+
try {
|
|
3406
|
+
const conversation = await xmtpClient.conversations.getConversationById(conversationId);
|
|
3407
|
+
if (!conversation) {
|
|
3408
|
+
return c.json({ error: "Conversation not found" }, 404);
|
|
3409
|
+
}
|
|
3410
|
+
await conversation.send(content);
|
|
3411
|
+
console.log(`\u27A1 Sent message to conversation ${conversationId}`);
|
|
3412
|
+
return c.json({
|
|
3413
|
+
success: true,
|
|
3414
|
+
action: "send",
|
|
3415
|
+
conversationId: payload.conversationId
|
|
3416
|
+
});
|
|
3417
|
+
} catch (error) {
|
|
3418
|
+
console.error("\u274C Error sending message:", error);
|
|
3419
|
+
return c.json({ error: "Failed to send message" }, 500);
|
|
3420
|
+
}
|
|
3421
|
+
});
|
|
3422
|
+
app.post("/reply", async (c) => {
|
|
3423
|
+
const xmtpClient = c.get("xmtpClient");
|
|
3424
|
+
if (!xmtpClient) {
|
|
3425
|
+
return c.json({ error: "XMTP client not initialized" }, 500);
|
|
3426
|
+
}
|
|
3427
|
+
const payload = getValidatedPayload(c);
|
|
3428
|
+
if (!payload) {
|
|
3429
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
3430
|
+
}
|
|
3431
|
+
const body = await c.req.json();
|
|
3432
|
+
const content = body.content || payload.content;
|
|
3433
|
+
if (!content) {
|
|
3434
|
+
return c.json({ error: "Content required for reply action" }, 400);
|
|
3435
|
+
}
|
|
3436
|
+
const messageId = body.messageId;
|
|
3437
|
+
if (!messageId) {
|
|
3438
|
+
return c.json(
|
|
3439
|
+
{ error: "Reference message ID required for reply action" },
|
|
3440
|
+
400
|
|
3441
|
+
);
|
|
3442
|
+
}
|
|
3443
|
+
try {
|
|
3444
|
+
const conversation = await xmtpClient.conversations.getConversationById(
|
|
3445
|
+
payload.conversationId
|
|
3446
|
+
);
|
|
3447
|
+
if (!conversation) {
|
|
3448
|
+
return c.json({ error: "Conversation not found" }, 404);
|
|
3449
|
+
}
|
|
3450
|
+
const reply = {
|
|
3451
|
+
reference: messageId,
|
|
3452
|
+
contentType: ContentTypeText,
|
|
3453
|
+
content
|
|
3454
|
+
};
|
|
3455
|
+
await conversation.send(reply, ContentTypeReply);
|
|
3456
|
+
console.log(
|
|
3457
|
+
`\u27A1 Sent reply "${content}" to conversation ${payload.conversationId}`
|
|
3458
|
+
);
|
|
3459
|
+
return c.json({
|
|
3460
|
+
success: true,
|
|
3461
|
+
action: "reply",
|
|
3462
|
+
conversationId: payload.conversationId
|
|
3463
|
+
});
|
|
3464
|
+
} catch (error) {
|
|
3465
|
+
console.error("\u274C Error sending reply:", error);
|
|
3466
|
+
return c.json({ error: "Failed to send reply" }, 500);
|
|
3467
|
+
}
|
|
3468
|
+
});
|
|
3469
|
+
app.post("/react", async (c) => {
|
|
3470
|
+
const xmtpClient = c.get("xmtpClient");
|
|
3471
|
+
if (!xmtpClient) {
|
|
3472
|
+
return c.json({ error: "XMTP client not initialized" }, 500);
|
|
3473
|
+
}
|
|
3474
|
+
const payload = getValidatedPayload(c);
|
|
3475
|
+
if (!payload) {
|
|
3476
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
3477
|
+
}
|
|
3478
|
+
const body = await c.req.json();
|
|
3479
|
+
if (!body.emoji) {
|
|
3480
|
+
return c.json({ error: "Emoji required for react action" }, 400);
|
|
3481
|
+
}
|
|
3482
|
+
try {
|
|
3483
|
+
const conversation = await xmtpClient.conversations.getConversationById(
|
|
3484
|
+
payload.conversationId
|
|
3485
|
+
);
|
|
3486
|
+
if (!conversation) {
|
|
3487
|
+
return c.json({ error: "Conversation not found" }, 404);
|
|
3488
|
+
}
|
|
3489
|
+
const reaction = {
|
|
3490
|
+
schema: "unicode",
|
|
3491
|
+
reference: body.messageId,
|
|
3492
|
+
action: body.action,
|
|
3493
|
+
contentType: ContentTypeReaction,
|
|
3494
|
+
content: body.emoji
|
|
3495
|
+
};
|
|
3496
|
+
await conversation.send(reaction, ContentTypeReaction);
|
|
3497
|
+
console.log(
|
|
3498
|
+
`\u27A1 Sent reaction ${body.emoji} to message ${body.messageId} in conversation ${payload.conversationId}`
|
|
3499
|
+
);
|
|
3500
|
+
return c.json({
|
|
3501
|
+
success: true,
|
|
3502
|
+
action: "react",
|
|
3503
|
+
conversationId: payload.conversationId
|
|
3504
|
+
});
|
|
3505
|
+
} catch (error) {
|
|
3506
|
+
console.error("\u274C Error sending reaction:", error);
|
|
3507
|
+
return c.json({ error: "Failed to send reaction" }, 500);
|
|
3508
|
+
}
|
|
3509
|
+
});
|
|
3510
|
+
app.post("/transaction", async (c) => {
|
|
3511
|
+
const xmtpClient = c.get("xmtpClient");
|
|
3512
|
+
if (!xmtpClient) {
|
|
3513
|
+
return c.json({ error: "XMTP client not initialized" }, 500);
|
|
3514
|
+
}
|
|
3515
|
+
const payload = getValidatedPayload(c);
|
|
3516
|
+
if (!payload) {
|
|
3517
|
+
return c.json({ error: "Invalid or expired token" }, 401);
|
|
3518
|
+
}
|
|
3519
|
+
let body = {};
|
|
3520
|
+
try {
|
|
3521
|
+
body = await c.req.json();
|
|
3522
|
+
} catch (error) {
|
|
3523
|
+
body = {};
|
|
3524
|
+
}
|
|
3525
|
+
const fromAddress = payload.fromAddress || body.fromAddress;
|
|
3526
|
+
const chainId = payload.chainId || body.chainId;
|
|
3527
|
+
const calls = payload.calls || body.calls;
|
|
3528
|
+
if (!calls || !fromAddress || !chainId) {
|
|
3529
|
+
return c.json(
|
|
3530
|
+
{ error: "Transaction data required for transaction action" },
|
|
3531
|
+
400
|
|
3532
|
+
);
|
|
3533
|
+
}
|
|
3534
|
+
calls.forEach((call, index) => {
|
|
3535
|
+
if (call.data && typeof call.data === "string") {
|
|
3536
|
+
const actualStart = call.data.substring(0, 10);
|
|
3537
|
+
if (actualStart === "0x010f2e2e") {
|
|
3538
|
+
console.error("\u{1F6A8} CRITICAL: Transaction data truncation detected!");
|
|
3539
|
+
console.error(" Function selector corrupted - transaction will fail");
|
|
3540
|
+
console.error(
|
|
3541
|
+
" This indicates a bug in wallet software or XMTP transmission"
|
|
3542
|
+
);
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
});
|
|
3546
|
+
try {
|
|
3547
|
+
const conversation = await xmtpClient.conversations.getConversationById(
|
|
3548
|
+
payload.conversationId
|
|
3549
|
+
);
|
|
3550
|
+
if (!conversation) {
|
|
3551
|
+
return c.json({ error: "Conversation not found" }, 404);
|
|
3552
|
+
}
|
|
3553
|
+
const params = {
|
|
3554
|
+
version: "1",
|
|
3555
|
+
chainId,
|
|
3556
|
+
from: fromAddress,
|
|
3557
|
+
calls
|
|
3558
|
+
};
|
|
3559
|
+
await conversation.send(params, ContentTypeWalletSendCalls);
|
|
3560
|
+
console.log(
|
|
3561
|
+
`\u2705 Sent transaction request to conversation ${payload.conversationId}`
|
|
3562
|
+
);
|
|
3563
|
+
return c.json({
|
|
3564
|
+
success: true,
|
|
3565
|
+
action: "transaction",
|
|
3566
|
+
conversationId: payload.conversationId
|
|
3567
|
+
});
|
|
3568
|
+
} catch (error) {
|
|
3569
|
+
console.error("\u274C Error sending transaction:", error);
|
|
3570
|
+
return c.json({ error: "Failed to send transaction" }, 500);
|
|
3571
|
+
}
|
|
3572
|
+
});
|
|
3573
|
+
var endpoints_default = app;
|
|
3574
|
+
|
|
3575
|
+
// src/plugin.ts
|
|
3576
|
+
function XMTPPlugin({
|
|
3577
|
+
filter
|
|
3578
|
+
} = {}) {
|
|
3579
|
+
return {
|
|
3580
|
+
name: "xmtp",
|
|
3581
|
+
description: "Provides XMTP messaging functionality",
|
|
3582
|
+
apply: (app2, context) => {
|
|
3583
|
+
app2.route("/xmtp-tools", endpoints_default);
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
}
|
|
3587
|
+
|
|
3253
3588
|
// src/index.ts
|
|
3254
3589
|
import {
|
|
3255
3590
|
Client,
|
|
@@ -3258,12 +3593,12 @@ import {
|
|
|
3258
3593
|
import {
|
|
3259
3594
|
ContentTypeTransactionReference
|
|
3260
3595
|
} from "@xmtp/content-type-transaction-reference";
|
|
3261
|
-
import { ContentTypeText } from "@xmtp/content-type-text";
|
|
3596
|
+
import { ContentTypeText as ContentTypeText2 } from "@xmtp/content-type-text";
|
|
3262
3597
|
import {
|
|
3263
|
-
ContentTypeReaction
|
|
3598
|
+
ContentTypeReaction as ContentTypeReaction2
|
|
3264
3599
|
} from "@xmtp/content-type-reaction";
|
|
3265
3600
|
import {
|
|
3266
|
-
ContentTypeReply,
|
|
3601
|
+
ContentTypeReply as ContentTypeReply2,
|
|
3267
3602
|
ReplyCodec as ReplyCodec2
|
|
3268
3603
|
} from "@xmtp/content-type-reply";
|
|
3269
3604
|
import {
|
|
@@ -3271,18 +3606,18 @@ import {
|
|
|
3271
3606
|
GroupUpdatedCodec
|
|
3272
3607
|
} from "@xmtp/content-type-group-updated";
|
|
3273
3608
|
import {
|
|
3274
|
-
ContentTypeWalletSendCalls
|
|
3609
|
+
ContentTypeWalletSendCalls as ContentTypeWalletSendCalls2
|
|
3275
3610
|
} from "@xmtp/content-type-wallet-send-calls";
|
|
3276
3611
|
export {
|
|
3277
3612
|
BasenameResolver,
|
|
3278
3613
|
BasenameTextRecordKeys,
|
|
3279
3614
|
Client,
|
|
3280
3615
|
ContentTypeGroupUpdated,
|
|
3281
|
-
ContentTypeReaction,
|
|
3282
|
-
ContentTypeReply,
|
|
3283
|
-
ContentTypeText,
|
|
3616
|
+
ContentTypeReaction2 as ContentTypeReaction,
|
|
3617
|
+
ContentTypeReply2 as ContentTypeReply,
|
|
3618
|
+
ContentTypeText2 as ContentTypeText,
|
|
3284
3619
|
ContentTypeTransactionReference,
|
|
3285
|
-
ContentTypeWalletSendCalls,
|
|
3620
|
+
ContentTypeWalletSendCalls2 as ContentTypeWalletSendCalls,
|
|
3286
3621
|
DEFAULT_AMOUNT,
|
|
3287
3622
|
DEFAULT_OPTIONS,
|
|
3288
3623
|
ENSResolver,
|
|
@@ -3293,6 +3628,7 @@ export {
|
|
|
3293
3628
|
ReplyCodec2 as ReplyCodec,
|
|
3294
3629
|
Resolver,
|
|
3295
3630
|
XMTPConnectionManager,
|
|
3631
|
+
XMTPPlugin,
|
|
3296
3632
|
XmtpResolver,
|
|
3297
3633
|
XmtpServiceClient,
|
|
3298
3634
|
backupDbToPersistentStorage,
|
|
@@ -3309,6 +3645,7 @@ export {
|
|
|
3309
3645
|
extractMentionedNames,
|
|
3310
3646
|
extractSubjects,
|
|
3311
3647
|
generateEncryptionKeyHex,
|
|
3648
|
+
generateXMTPToolsToken,
|
|
3312
3649
|
getDbPath,
|
|
3313
3650
|
getEncryptionKeyFromHex,
|
|
3314
3651
|
getXMTPToolsUrl,
|