@hybrd/xmtp 1.2.8 → 1.3.1

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.
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @hybrd/xmtp@1.2.8 build /Users/ian/Projects/01/hybrid/packages/xmtp
3
+ > @hybrd/xmtp@1.3.1 build /Users/ian/Projects/01/hybrid/packages/xmtp
4
4
  > tsup
5
5
 
6
6
  CLI Building entry: {"index":"src/index.ts"}
@@ -12,7 +12,7 @@
12
12
  CJS Build start
13
13
  ESM Build start
14
14
 
15
- [12:41:54 PM]  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
15
+ [2:26:40 PM]  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
16
16
 
17
17
  scripts/revoke-installations.ts:89:4:
18
18
   89 │ if (import.meta.url === file://${process.argv[1]}) {
@@ -23,7 +23,7 @@
23
23
 
24
24
 
25
25
 
26
- [12:41:54 PM]  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
26
+ [2:26:40 PM]  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
27
27
 
28
28
  src/client.ts:21:33:
29
29
   21 │ const __filename = fileURLToPath(import.meta.url)
@@ -33,13 +33,13 @@
33
33
 
34
34
 
35
35
 
36
- ESM dist/index.js 104.11 KB
37
- ESM dist/index.js.map 194.82 KB
38
- ESM ⚡️ Build success in 38ms
39
- CJS dist/index.cjs 109.24 KB
40
- CJS dist/index.cjs.map 195.29 KB
41
- CJS ⚡️ Build success in 38ms
36
+ ESM dist/index.js 114.51 KB
37
+ ESM dist/index.js.map 218.75 KB
38
+ ESM ⚡️ Build success in 101ms
39
+ CJS dist/index.cjs 119.82 KB
40
+ CJS dist/index.cjs.map 219.25 KB
41
+ CJS ⚡️ Build success in 101ms
42
42
  DTS Build start
43
- DTS ⚡️ Build success in 3465ms
44
- DTS dist/index.d.cts 27.42 KB
45
- DTS dist/index.d.ts 27.42 KB
43
+ DTS ⚡️ Build success in 3819ms
44
+ DTS dist/index.d.cts 29.23 KB
45
+ DTS dist/index.d.ts 29.23 KB
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @hybrd/xmtp@1.2.3 lint:fix /Users/ian/Projects/01/hybrid/packages/xmtp
3
+ > @hybrd/xmtp@1.2.8 lint:fix /Users/ian/Projects/01/hybrid/packages/xmtp
4
4
  > biome lint --write --unsafe
5
5
 
6
- Checked 24 files in 26ms. No fixes applied.
6
+ Checked 27 files in 18ms. No fixes applied.
@@ -0,0 +1,5 @@
1
+
2
+ 
3
+ > @hybrd/xmtp@1.2.8 typecheck /Users/ian/Projects/01/hybrid/packages/xmtp
4
+ > tsc --noEmit
5
+
package/dist/index.cjs CHANGED
@@ -36,11 +36,11 @@ __export(src_exports, {
36
36
  BasenameTextRecordKeys: () => BasenameTextRecordKeys,
37
37
  Client: () => import_node_sdk2.Client,
38
38
  ContentTypeGroupUpdated: () => import_content_type_group_updated.ContentTypeGroupUpdated,
39
- ContentTypeReaction: () => import_content_type_reaction2.ContentTypeReaction,
40
- ContentTypeReply: () => import_content_type_reply2.ContentTypeReply,
41
- ContentTypeText: () => import_content_type_text.ContentTypeText,
39
+ ContentTypeReaction: () => import_content_type_reaction3.ContentTypeReaction,
40
+ ContentTypeReply: () => import_content_type_reply3.ContentTypeReply,
41
+ ContentTypeText: () => import_content_type_text2.ContentTypeText,
42
42
  ContentTypeTransactionReference: () => import_content_type_transaction_reference2.ContentTypeTransactionReference,
43
- ContentTypeWalletSendCalls: () => import_content_type_wallet_send_calls2.ContentTypeWalletSendCalls,
43
+ ContentTypeWalletSendCalls: () => import_content_type_wallet_send_calls3.ContentTypeWalletSendCalls,
44
44
  DEFAULT_AMOUNT: () => DEFAULT_AMOUNT,
45
45
  DEFAULT_OPTIONS: () => DEFAULT_OPTIONS,
46
46
  ENSResolver: () => ENSResolver,
@@ -48,9 +48,10 @@ __export(src_exports, {
48
48
  IdentifierKind: () => import_node_sdk2.IdentifierKind,
49
49
  MAX_USDC_AMOUNT: () => MAX_USDC_AMOUNT,
50
50
  MessageListener: () => MessageListener,
51
- ReplyCodec: () => import_content_type_reply2.ReplyCodec,
51
+ ReplyCodec: () => import_content_type_reply3.ReplyCodec,
52
52
  Resolver: () => Resolver,
53
53
  XMTPConnectionManager: () => XMTPConnectionManager,
54
+ XMTPPlugin: () => XMTPPlugin,
54
55
  XmtpResolver: () => XmtpResolver,
55
56
  XmtpServiceClient: () => XmtpServiceClient,
56
57
  backupDbToPersistentStorage: () => backupDbToPersistentStorage,
@@ -67,6 +68,7 @@ __export(src_exports, {
67
68
  extractMentionedNames: () => extractMentionedNames,
68
69
  extractSubjects: () => extractSubjects,
69
70
  generateEncryptionKeyHex: () => generateEncryptionKeyHex,
71
+ generateXMTPToolsToken: () => generateXMTPToolsToken,
70
72
  getDbPath: () => getDbPath,
71
73
  getEncryptionKeyFromHex: () => getEncryptionKeyFromHex,
72
74
  getXMTPToolsUrl: () => getXMTPToolsUrl,
@@ -3326,14 +3328,349 @@ function getXMTPToolsUrl(baseUrl, action, token) {
3326
3328
  return `${baseUrl}/xmtp-tools/${action}?token=${token}`;
3327
3329
  }
3328
3330
 
3331
+ // src/endpoints.ts
3332
+ var import_content_type_reaction2 = require("@xmtp/content-type-reaction");
3333
+ var import_content_type_reply2 = require("@xmtp/content-type-reply");
3334
+ var import_content_type_text = require("@xmtp/content-type-text");
3335
+ var import_content_type_wallet_send_calls2 = require("@xmtp/content-type-wallet-send-calls");
3336
+ var import_hono = require("hono");
3337
+
3338
+ // src/lib/jwt.ts
3339
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
3340
+ function getValidatedPayload(c) {
3341
+ const authHeader = c.req.header("Authorization");
3342
+ if (authHeader?.startsWith("Bearer ")) {
3343
+ const token2 = authHeader.substring(7);
3344
+ return validateXMTPToolsToken(token2);
3345
+ }
3346
+ const token = c.req.query("token");
3347
+ if (!token) {
3348
+ return null;
3349
+ }
3350
+ return validateXMTPToolsToken(token);
3351
+ }
3352
+ var JWT_SECRET = (() => {
3353
+ const secret = process.env.XMTP_ENCRYPTION_KEY;
3354
+ const nodeEnv = process.env.NODE_ENV || "development";
3355
+ if (nodeEnv === "production" && !secret) {
3356
+ throw new Error(
3357
+ "XMTP_ENCRYPTION_KEY environment variable is required in production. Generate a secure random secret for JWT token signing."
3358
+ );
3359
+ }
3360
+ if (!secret) {
3361
+ console.warn(
3362
+ "\u26A0\uFE0F [SECURITY] Using fallback JWT secret for development. Set XMTP_ENCRYPTION_KEY environment variable for production."
3363
+ );
3364
+ return "fallback-secret-for-dev-only";
3365
+ }
3366
+ return secret;
3367
+ })();
3368
+ var API_KEY = (() => {
3369
+ const apiKey = process.env.XMTP_API_KEY;
3370
+ const nodeEnv = process.env.NODE_ENV || "development";
3371
+ if (nodeEnv === "production" && !apiKey) {
3372
+ throw new Error(
3373
+ "XMTP_API_KEY environment variable is required in production. Generate a secure random API key for authentication."
3374
+ );
3375
+ }
3376
+ if (!apiKey) {
3377
+ console.warn(
3378
+ "\u26A0\uFE0F [SECURITY] Using fallback API key for development. Set XMTP_API_KEY environment variable for production."
3379
+ );
3380
+ return "fallback-api-key-for-dev-only";
3381
+ }
3382
+ return apiKey;
3383
+ })();
3384
+ var JWT_EXPIRY = 5 * 60;
3385
+ function generateXMTPToolsToken(payload) {
3386
+ const now = Math.floor(Date.now() / 1e3);
3387
+ const fullPayload = {
3388
+ ...payload,
3389
+ issued: now,
3390
+ expires: now + JWT_EXPIRY
3391
+ };
3392
+ return import_jsonwebtoken.default.sign(fullPayload, JWT_SECRET, {
3393
+ expiresIn: JWT_EXPIRY
3394
+ });
3395
+ }
3396
+ function validateXMTPToolsToken(token) {
3397
+ if (token === API_KEY) {
3398
+ console.log("\u{1F511} [Auth] Using API key authentication");
3399
+ const now = Math.floor(Date.now() / 1e3);
3400
+ return {
3401
+ action: "send",
3402
+ // Default action
3403
+ conversationId: "",
3404
+ // Will be filled by endpoint
3405
+ issued: now,
3406
+ expires: now + 3600
3407
+ // API keys are valid for 1 hour
3408
+ };
3409
+ }
3410
+ try {
3411
+ const decoded = import_jsonwebtoken.default.verify(token, JWT_SECRET);
3412
+ console.log("\u{1F511} [Auth] Using JWT token authentication");
3413
+ const now = Math.floor(Date.now() / 1e3);
3414
+ if (decoded.expires < now) {
3415
+ console.warn("\u{1F512} XMTP tools token has expired");
3416
+ return null;
3417
+ }
3418
+ return decoded;
3419
+ } catch (error) {
3420
+ console.error(
3421
+ "\u{1F512} Invalid XMTP tools token and not matching API key:",
3422
+ error
3423
+ );
3424
+ return null;
3425
+ }
3426
+ }
3427
+
3428
+ // src/endpoints.ts
3429
+ var app = new import_hono.Hono();
3430
+ app.get("/messages/:messageId", async (c) => {
3431
+ const xmtpClient = c.get("xmtpClient");
3432
+ if (!xmtpClient) {
3433
+ return c.json({ error: "XMTP client not initialized" }, 500);
3434
+ }
3435
+ const token = c.req.query("token");
3436
+ if (!token) {
3437
+ return c.json({ error: "Token required" }, 401);
3438
+ }
3439
+ const payload = validateXMTPToolsToken(token);
3440
+ if (!payload) {
3441
+ return c.json({ error: "Invalid or expired token" }, 401);
3442
+ }
3443
+ const messageId = c.req.param("messageId");
3444
+ try {
3445
+ const message = await xmtpClient.conversations.getMessageById(messageId);
3446
+ if (!message) {
3447
+ return c.json({ error: "Message not found" }, 404);
3448
+ }
3449
+ console.log(`\u2705 Retrieved message ${messageId}`);
3450
+ const transformedMessage = {
3451
+ id: message.id,
3452
+ senderInboxId: message.senderInboxId,
3453
+ sentAt: message.sentAt.toISOString(),
3454
+ content: typeof message.content === "object" ? JSON.stringify(message.content) : message.content,
3455
+ contentType: message.contentType?.typeId || "text",
3456
+ conversationId: message.conversationId,
3457
+ parameters: message.contentType?.parameters || {}
3458
+ };
3459
+ return c.json(transformedMessage);
3460
+ } catch (error) {
3461
+ console.error("\u274C Error fetching message:", error);
3462
+ return c.json({ error: "Failed to fetch message" }, 500);
3463
+ }
3464
+ });
3465
+ app.post("/send", async (c) => {
3466
+ const xmtpClient = c.get("xmtpClient");
3467
+ if (!xmtpClient) {
3468
+ return c.json({ error: "XMTP client not initialized" }, 500);
3469
+ }
3470
+ const payload = getValidatedPayload(c);
3471
+ if (!payload) {
3472
+ return c.json({ error: "Invalid or expired token" }, 401);
3473
+ }
3474
+ const body = await c.req.json();
3475
+ const content = body.content || payload.content;
3476
+ if (!content) {
3477
+ return c.json({ error: "Content required for send action" }, 400);
3478
+ }
3479
+ const conversationId = payload.conversationId;
3480
+ if (!conversationId) {
3481
+ return c.json({ error: "Conversation ID required" }, 400);
3482
+ }
3483
+ try {
3484
+ const conversation = await xmtpClient.conversations.getConversationById(conversationId);
3485
+ if (!conversation) {
3486
+ return c.json({ error: "Conversation not found" }, 404);
3487
+ }
3488
+ await conversation.send(content);
3489
+ console.log(`\u27A1 Sent message to conversation ${conversationId}`);
3490
+ return c.json({
3491
+ success: true,
3492
+ action: "send",
3493
+ conversationId: payload.conversationId
3494
+ });
3495
+ } catch (error) {
3496
+ console.error("\u274C Error sending message:", error);
3497
+ return c.json({ error: "Failed to send message" }, 500);
3498
+ }
3499
+ });
3500
+ app.post("/reply", async (c) => {
3501
+ const xmtpClient = c.get("xmtpClient");
3502
+ if (!xmtpClient) {
3503
+ return c.json({ error: "XMTP client not initialized" }, 500);
3504
+ }
3505
+ const payload = getValidatedPayload(c);
3506
+ if (!payload) {
3507
+ return c.json({ error: "Invalid or expired token" }, 401);
3508
+ }
3509
+ const body = await c.req.json();
3510
+ const content = body.content || payload.content;
3511
+ if (!content) {
3512
+ return c.json({ error: "Content required for reply action" }, 400);
3513
+ }
3514
+ const messageId = body.messageId;
3515
+ if (!messageId) {
3516
+ return c.json(
3517
+ { error: "Reference message ID required for reply action" },
3518
+ 400
3519
+ );
3520
+ }
3521
+ try {
3522
+ const conversation = await xmtpClient.conversations.getConversationById(
3523
+ payload.conversationId
3524
+ );
3525
+ if (!conversation) {
3526
+ return c.json({ error: "Conversation not found" }, 404);
3527
+ }
3528
+ const reply = {
3529
+ reference: messageId,
3530
+ contentType: import_content_type_text.ContentTypeText,
3531
+ content
3532
+ };
3533
+ await conversation.send(reply, import_content_type_reply2.ContentTypeReply);
3534
+ console.log(
3535
+ `\u27A1 Sent reply "${content}" to conversation ${payload.conversationId}`
3536
+ );
3537
+ return c.json({
3538
+ success: true,
3539
+ action: "reply",
3540
+ conversationId: payload.conversationId
3541
+ });
3542
+ } catch (error) {
3543
+ console.error("\u274C Error sending reply:", error);
3544
+ return c.json({ error: "Failed to send reply" }, 500);
3545
+ }
3546
+ });
3547
+ app.post("/react", async (c) => {
3548
+ const xmtpClient = c.get("xmtpClient");
3549
+ if (!xmtpClient) {
3550
+ return c.json({ error: "XMTP client not initialized" }, 500);
3551
+ }
3552
+ const payload = getValidatedPayload(c);
3553
+ if (!payload) {
3554
+ return c.json({ error: "Invalid or expired token" }, 401);
3555
+ }
3556
+ const body = await c.req.json();
3557
+ if (!body.emoji) {
3558
+ return c.json({ error: "Emoji required for react action" }, 400);
3559
+ }
3560
+ try {
3561
+ const conversation = await xmtpClient.conversations.getConversationById(
3562
+ payload.conversationId
3563
+ );
3564
+ if (!conversation) {
3565
+ return c.json({ error: "Conversation not found" }, 404);
3566
+ }
3567
+ const reaction = {
3568
+ schema: "unicode",
3569
+ reference: body.messageId,
3570
+ action: body.action,
3571
+ contentType: import_content_type_reaction2.ContentTypeReaction,
3572
+ content: body.emoji
3573
+ };
3574
+ await conversation.send(reaction, import_content_type_reaction2.ContentTypeReaction);
3575
+ console.log(
3576
+ `\u27A1 Sent reaction ${body.emoji} to message ${body.messageId} in conversation ${payload.conversationId}`
3577
+ );
3578
+ return c.json({
3579
+ success: true,
3580
+ action: "react",
3581
+ conversationId: payload.conversationId
3582
+ });
3583
+ } catch (error) {
3584
+ console.error("\u274C Error sending reaction:", error);
3585
+ return c.json({ error: "Failed to send reaction" }, 500);
3586
+ }
3587
+ });
3588
+ app.post("/transaction", async (c) => {
3589
+ const xmtpClient = c.get("xmtpClient");
3590
+ if (!xmtpClient) {
3591
+ return c.json({ error: "XMTP client not initialized" }, 500);
3592
+ }
3593
+ const payload = getValidatedPayload(c);
3594
+ if (!payload) {
3595
+ return c.json({ error: "Invalid or expired token" }, 401);
3596
+ }
3597
+ let body = {};
3598
+ try {
3599
+ body = await c.req.json();
3600
+ } catch (error) {
3601
+ body = {};
3602
+ }
3603
+ const fromAddress = payload.fromAddress || body.fromAddress;
3604
+ const chainId = payload.chainId || body.chainId;
3605
+ const calls = payload.calls || body.calls;
3606
+ if (!calls || !fromAddress || !chainId) {
3607
+ return c.json(
3608
+ { error: "Transaction data required for transaction action" },
3609
+ 400
3610
+ );
3611
+ }
3612
+ calls.forEach((call, index) => {
3613
+ if (call.data && typeof call.data === "string") {
3614
+ const actualStart = call.data.substring(0, 10);
3615
+ if (actualStart === "0x010f2e2e") {
3616
+ console.error("\u{1F6A8} CRITICAL: Transaction data truncation detected!");
3617
+ console.error(" Function selector corrupted - transaction will fail");
3618
+ console.error(
3619
+ " This indicates a bug in wallet software or XMTP transmission"
3620
+ );
3621
+ }
3622
+ }
3623
+ });
3624
+ try {
3625
+ const conversation = await xmtpClient.conversations.getConversationById(
3626
+ payload.conversationId
3627
+ );
3628
+ if (!conversation) {
3629
+ return c.json({ error: "Conversation not found" }, 404);
3630
+ }
3631
+ const params = {
3632
+ version: "1",
3633
+ chainId,
3634
+ from: fromAddress,
3635
+ calls
3636
+ };
3637
+ await conversation.send(params, import_content_type_wallet_send_calls2.ContentTypeWalletSendCalls);
3638
+ console.log(
3639
+ `\u2705 Sent transaction request to conversation ${payload.conversationId}`
3640
+ );
3641
+ return c.json({
3642
+ success: true,
3643
+ action: "transaction",
3644
+ conversationId: payload.conversationId
3645
+ });
3646
+ } catch (error) {
3647
+ console.error("\u274C Error sending transaction:", error);
3648
+ return c.json({ error: "Failed to send transaction" }, 500);
3649
+ }
3650
+ });
3651
+ var endpoints_default = app;
3652
+
3653
+ // src/plugin.ts
3654
+ function XMTPPlugin({
3655
+ filter
3656
+ } = {}) {
3657
+ return {
3658
+ name: "xmtp",
3659
+ description: "Provides XMTP messaging functionality",
3660
+ apply: (app2, context) => {
3661
+ app2.route("/xmtp-tools", endpoints_default);
3662
+ }
3663
+ };
3664
+ }
3665
+
3329
3666
  // src/index.ts
3330
3667
  var import_node_sdk2 = require("@xmtp/node-sdk");
3331
3668
  var import_content_type_transaction_reference2 = require("@xmtp/content-type-transaction-reference");
3332
- var import_content_type_text = require("@xmtp/content-type-text");
3333
- var import_content_type_reaction2 = require("@xmtp/content-type-reaction");
3334
- var import_content_type_reply2 = require("@xmtp/content-type-reply");
3669
+ var import_content_type_text2 = require("@xmtp/content-type-text");
3670
+ var import_content_type_reaction3 = require("@xmtp/content-type-reaction");
3671
+ var import_content_type_reply3 = require("@xmtp/content-type-reply");
3335
3672
  var import_content_type_group_updated = require("@xmtp/content-type-group-updated");
3336
- var import_content_type_wallet_send_calls2 = require("@xmtp/content-type-wallet-send-calls");
3673
+ var import_content_type_wallet_send_calls3 = require("@xmtp/content-type-wallet-send-calls");
3337
3674
  // Annotate the CommonJS export names for ESM import in node:
3338
3675
  0 && (module.exports = {
3339
3676
  BasenameResolver,
@@ -3355,6 +3692,7 @@ var import_content_type_wallet_send_calls2 = require("@xmtp/content-type-wallet-
3355
3692
  ReplyCodec,
3356
3693
  Resolver,
3357
3694
  XMTPConnectionManager,
3695
+ XMTPPlugin,
3358
3696
  XmtpResolver,
3359
3697
  XmtpServiceClient,
3360
3698
  backupDbToPersistentStorage,
@@ -3371,6 +3709,7 @@ var import_content_type_wallet_send_calls2 = require("@xmtp/content-type-wallet-
3371
3709
  extractMentionedNames,
3372
3710
  extractSubjects,
3373
3711
  generateEncryptionKeyHex,
3712
+ generateXMTPToolsToken,
3374
3713
  getDbPath,
3375
3714
  getEncryptionKeyFromHex,
3376
3715
  getXMTPToolsUrl,